home *** CD-ROM | disk | FTP | other *** search
- /*
- * Modifications Copyright 1993, 1994, 1995, 1996, 1999, 2000 by Paul Mattes.
- * Original X11 Port Copyright 1990 by Jeff Sparkes.
- * Permission to use, copy, modify, and distribute this software and its
- * documentation for any purpose and without fee is hereby granted,
- * provided that the above copyright notice appear in all copies and that
- * both that copyright notice and this permission notice appear in
- * supporting documentation.
- *
- * Copyright 1989 by Georgia Tech Research Corporation, Atlanta, GA 30332.
- * All Rights Reserved. GTRC hereby grants public use of this software.
- * Derivative works based on this software must incorporate this copyright
- * notice.
- */
-
- /*
- * screen.c
- * This module handles the X display. It has been extensively
- * optimized to minimize X drawing operations.
- */
-
- #include "globals.h"
- #include <X11/IntrinsicP.h>
- #include <X11/StringDefs.h>
- #include <X11/Xatom.h>
- #include <X11/Shell.h>
- #include <X11/Composite.h>
- #include <X11/Xaw/Dialog.h>
- #include <X11/Xaw/Scrollbar.h>
- #include "Husk.h"
- #include <X11/cursorfont.h>
- #include <X11/keysym.h>
- #include <errno.h>
- #include "3270ds.h"
- #include "appres.h"
- #include "screen.h"
- #include "ctlr.h"
- #include "cg.h"
- #include "resources.h"
-
- #include "actionsc.h"
- #include "ansic.h"
- #include "charsetc.h"
- #include "ctlrc.h"
- #include "hostc.h"
- #include "keymapc.h"
- #include "keypadc.h"
- #include "kybdc.h"
- #include "menubarc.h"
- #include "popupsc.h"
- #include "savec.h"
- #include "screenc.h"
- #include "scrollc.h"
- #include "statusc.h"
- #include "tablesc.h"
- #include "trace_dsc.h"
- #include "utilc.h"
- #include "xioc.h"
-
- #if defined(HAVE_SYS_SELECT_H) /*[*/
- #include <sys/select.h> /* fd_set declaration */
- #endif /*]*/
-
- #include "x3270.bm"
- #include "wait.bm"
-
- #define SCROLLBAR_WIDTH 15
- /* #define _ST */
-
- /* Externals: main.c */
- extern int default_screen;
-
- /* Externals: ctlr.c */
- extern Boolean screen_changed;
- extern int first_changed;
- extern int last_changed;
-
- /* Globals */
- unsigned char *selected; /* selection bitmap */
- Dimension main_width;
- #include <X11/bitmaps/gray>
- Boolean scrollbar_changed = False;
- Boolean model_changed = False;
- Boolean efont_changed = False;
- Boolean oversize_changed = False;
- Boolean scheme_changed = False;
- Pixel keypadbg_pixel;
- Boolean flipped = False;
- Pixmap icon;
- Boolean shifted = False;
- struct font_list *font_list = (struct font_list *) NULL;
- int font_count = 0;
- char *efontname;
-
- /* Statics */
- static Dimension main_height;
- static union sp *temp_image; /* temporary for X display */
- static Pixel colorbg_pixel;
- static Boolean cursor_displayed = False;
- static Boolean cursor_enabled = True;
- static Boolean cursor_blink_pending = False;
- static XtIntervalId cursor_blink_id;
- static int field_colors[4];
- static Boolean in_focus = False;
- static Boolean line_changed = False;
- static Boolean cursor_changed = False;
- static Boolean iconic = False;
- static Widget container;
- static Widget scrollbar;
- static Dimension menubar_height;
- #if defined(X3270_KEYPAD) /*[*/
- static Dimension keypad_height;
- static Dimension keypad_xwidth;
- #endif /*]*/
- static Dimension container_width;
- static Dimension cwidth_nkp;
- static Dimension container_height;
- static Dimension scrollbar_width;
- static char *aicon_text = CN;
- static XFontStruct *ailabel_font;
- static Dimension aicon_label_height = 0;
- static GC ailabel_gc;
- static Pixel cpx[16];
- static Boolean cpx_done[16];
- static Pixel normal_pixel;
- static Pixel select_pixel;
- static Pixel bold_pixel;
- static Pixel selbg_pixel;
- static Pixel cursor_pixel;
- static Boolean text_blinking_on = True;
- static Boolean text_blinkers_exist = False;
- static Boolean text_blink_scheduled = False;
- static XtIntervalId text_blink_id;
- static XtTranslations screen_t00 = NULL;
- static XtTranslations screen_t0 = NULL;
- static XtTranslations container_t00 = NULL;
- static XtTranslations container_t0 = NULL;
- static unsigned char *rt_buf8 = (unsigned char *) NULL;
- static XChar2b *rt_buf16 = (XChar2b *) NULL;
- static char *color_name[16] = {
- (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL,
- (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL,
- (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL,
- (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL
- };
- static Boolean configure_ticking = False;
- static XtIntervalId configure_id;
-
- static Pixmap inv_icon;
- static Pixmap wait_icon;
- static Pixmap inv_wait_icon;
- static Boolean icon_inverted = False;
- static Widget icon_shell;
-
- static struct font_list *font_last = (struct font_list *) NULL;
-
- /* Globals for undoing reconfigurations. */
- static enum {
- REDO_NONE,
- REDO_FONT,
- #if defined(X3270_MENUS) /*[*/
- REDO_MODEL,
- #endif /*]*/
- #if defined(X3270_KEYPAD) /*[*/
- REDO_KEYPAD,
- #endif /*]*/
- REDO_SCROLLBAR,
- REDO_RESIZE
- } screen_redo = REDO_NONE;
- static char *redo_old_font = CN;
- #if defined(X3270_MENUS) /*[*/
- static int redo_old_model;
- static int redo_old_ov_cols;
- static int redo_old_ov_rows;
- #endif /*]*/
-
- static unsigned char blank_map[32];
- #define BKM_SET(n) blank_map[(n)/8] |= 1 << ((n)%8)
- #define BKM_ISSET(n) ((blank_map[(n)/8] & (1 << ((n)%8))) != 0)
-
- enum fallback_color { FB_WHITE, FB_BLACK };
- static enum fallback_color ibm_fb = FB_WHITE;
-
- /*
- * The screen state structure. This structure is swapped whenever we switch
- * between normal and active-iconic states.
- */
- #define NGCS 16
- struct sstate {
- Widget widget; /* the widget */
- Window window; /* the window */
- union sp *image; /* what's on the X display */
- int cursor_daddr; /* displayed cursor address */
- Boolean exposed_yet; /* have we been exposed yet? */
- Boolean overstrike; /* are we overstriking? */
- Dimension screen_width; /* screen dimensions in pixels */
- Dimension screen_height;
- GC gc[NGCS * 2], /* standard, inverted GCs */
- selgc[NGCS], /* color selected text GCs */
- mcgc, /* monochrome block cursor GC */
- ucgc, /* unique-cursor-color cursor GC */
- invucgc;/* inverse ucgc */
- int char_height;
- int char_width;
- Font fid;
- int ascent;
- int descent;
- Boolean standard_font;
- Boolean extended_3270font;
- Boolean latin1_font;
- Boolean debugging_font;
- Boolean obscured;
- Boolean copied;
- unsigned char *xfmap; /* standard font CG-to-ASCII map */
- };
- static struct sstate nss;
- static struct sstate iss;
- static struct sstate *ss = &nss;
-
- /* Globals based on nss, used mostly by status and select routines. */
- Widget *screen = &nss.widget;
- Window *screen_window = &nss.window;
- int *char_width = &nss.char_width;
- int *char_height = &nss.char_height;
- int *ascent = &nss.ascent;
- int *descent = &nss.descent;
- Boolean *standard_font = &nss.standard_font;
- Boolean *latin1_font = &nss.latin1_font;
- Boolean *debugging_font = &nss.debugging_font;
- Boolean *extended_3270font = &nss.extended_3270font;
-
- /* Mouse-cursor state */
- enum mcursor_state { LOCKED, NORMAL, WAIT };
- static enum mcursor_state mcursor_state = LOCKED;
- static enum mcursor_state icon_cstate = NORMAL;
-
- static void aicon_init(void);
- static void aicon_reinit(unsigned cmask);
- static void screen_focus(Boolean in);
- static void make_gc_set(struct sstate *s, int i, Pixel fg, Pixel bg);
- static void make_gcs(struct sstate *s);
- static void put_cursor(int baddr, Boolean on);
- static void resync_display(union sp *buffer, int first, int last);
- static void draw_fields(union sp *buffer, int first, int last);
- static void render_text(union sp *buffer, int baddr, int len,
- Boolean block_cursor, union sp *attrs);
- static void cursor_pos(void);
- static void cursor_on(void);
- static void schedule_cursor_blink(void);
- static void schedule_text_blink(void);
- static void inflate_screen(void);
- static int fa_color(unsigned char fa);
- static Boolean cursor_off(void);
- static void draw_aicon_label(void);
- static void set_mcursor(void);
- static void scrollbar_init(Boolean is_reset);
- static void init_rsfonts(void);
- static void allocate_pixels(void);
- static int fl_baddr(int baddr);
- static GC get_gc(struct sstate *s, int color);
- static GC get_selgc(struct sstate *s, int color);
- static void default_color_scheme(void);
- static Boolean xfer_color_scheme(char *cs, Boolean do_popup);
- static void set_font_globals(XFontStruct *f, const char *ef, Font ff);
- static void screen_connect(Boolean ignored);
- static void configure_stable(XtPointer closure, XtIntervalId *id);
- static void cancel_blink(void);
- static void render_blanks(int baddr, int height, union sp *buffer);
- static void resync_text(int baddr, int len, union sp *buffer);
- static void screen_reinit(unsigned cmask);
- static void aicon_font_init(void);
- static void aicon_size(Dimension *iw, Dimension *ih);
- static void invert_icon(Boolean inverted);
- static const char *load_fixed_font(const char *name);
- static void lock_icon(enum mcursor_state state);
-
- /* Resize font list. */
- struct rsfont {
- struct rsfont *next;
- char *name;
- int width;
- int height;
- int total_width; /* transient */
- int total_height; /* transient */
- int area; /* transient */
- };
- static struct rsfont *rsfonts;
-
- #define BASE_MASK 0x0f /* mask for 16 actual colors */
- #define INVERT_MASK 0x10 /* toggle for inverted colors */
- #define GC_NONDEFAULT 0x20 /* distinguishes "color 0" from zeroed
- memory */
-
- #define COLOR_MASK (GC_NONDEFAULT | BASE_MASK)
- #define INVERT_COLOR(c) ((c) ^ INVERT_MASK)
- #define NO_INVERT(c) ((c) & ~INVERT_MASK)
-
- #define DEFAULT_PIXEL (appres.m3279 ? COLOR_BLUE : FA_INT_NORM_NSEL)
- #define PIXEL_INDEX(c) ((c) & BASE_MASK)
-
-
- /*
- * Save 00 event translations.
- */
- void
- save_00translations(Widget w, XtTranslations *t00)
- {
- *t00 = w->core.tm.translations;
- }
-
- /*
- * Define our event translations
- */
- void
- set_translations(Widget w, XtTranslations *t00, XtTranslations *t0)
- {
- struct trans_list *t;
-
- if (t00 != (XtTranslations *)NULL)
- XtOverrideTranslations(w, *t00);
-
- for (t = trans_list; t != NULL; t = t->next)
- XtOverrideTranslations(w, lookup_tt(t->name, CN));
-
- *t0 = w->core.tm.translations;
- }
-
- /*
- * Add or clear a temporary keymap.
- */
- void
- screen_set_temp_keymap(XtTranslations trans)
- {
- if (trans != (XtTranslations)NULL) {
- XtOverrideTranslations(nss.widget, trans);
- XtOverrideTranslations(container, trans);
- } else {
- XtUninstallTranslations(nss.widget);
- XtOverrideTranslations(nss.widget, screen_t0);
- XtUninstallTranslations(container);
- XtOverrideTranslations(container, container_t0);
- }
- }
-
- /*
- * Change the baselevel keymap.
- */
- void
- screen_set_keymap(void)
- {
- XtUninstallTranslations(nss.widget);
- set_translations(nss.widget, &screen_t00, &screen_t0);
- XtUninstallTranslations(container);
- set_translations(container, &container_t00, &container_t0);
- }
-
-
- /*
- * Initialize the screen.
- */
- void
- screen_init(void)
- {
- register int i;
-
- /* Initialize ss. */
- nss.cursor_daddr = 0;
- nss.exposed_yet = False;
-
- /* Initialize "gray" bitmap. */
- if (appres.mono)
- gray = XCreatePixmapFromBitmapData(display,
- root_window, (char *)gray_bits,
- gray_width, gray_height,
- appres.foreground, appres.background, screen_depth);
-
- /* Initialize the resize list. */
- init_rsfonts();
-
- /* Initialize the blank map. */
- (void) memset((char *)blank_map, '\0', sizeof(blank_map));
- BKM_SET(CG_null);
- BKM_SET(CG_nobreakspace);
- BKM_SET(CG_ff);
- BKM_SET(CG_cr);
- BKM_SET(CG_nl);
- BKM_SET(CG_em);
- BKM_SET(CG_space);
- for (i = 0; i <= 0xf; i++) {
- BKM_SET(0xc0 + i);
- BKM_SET(0xe0 + i);
- }
-
- /* Register state change callbacks. */
- register_schange(ST_HALF_CONNECT, screen_connect);
- register_schange(ST_CONNECT, screen_connect);
- register_schange(ST_3270_MODE, screen_connect);
-
- /* Initialize the emulated 3270 controller hardware. */
- ctlr_init(ALL_CHANGE);
-
- /* Initialize the actve icon. */
- aicon_init();
-
- /* Initialize the status line. */
- status_init();
-
- /* Initialize the placement of the pop-up keypad. */
- keypad_placement_init();
-
- /* Now call the "reinitialize" function to set everything else up. */
- screen_reinit(ALL_CHANGE);
- }
-
- /*
- * Re-initialize the screen.
- */
- static void
- screen_reinit(unsigned cmask)
- {
- Dimension cwidth_curr;
- #if defined(X3270_KEYPAD) /*[*/
- Dimension mkw;
- #endif /*]*/
-
- /* Allocate colors. */
- if (cmask & COLOR_CHANGE) {
- if (appres.m3279) {
- default_color_scheme();
- (void) xfer_color_scheme(appres.color_scheme, False);
- }
- allocate_pixels();
- }
-
- /* Define graphics contexts. */
- if (cmask & (FONT_CHANGE | COLOR_CHANGE))
- make_gcs(&nss);
-
- /* Reinitialize the controller. */
- ctlr_reinit(cmask);
-
- /* Allocate buffers. */
- if (cmask & MODEL_CHANGE) {
- /* Selection bitmap */
- if (selected)
- XtFree((char *)selected);
- selected = (unsigned char *)XtCalloc(sizeof(unsigned char),
- (maxROWS * maxCOLS + 7) / 8);
-
- /* X display image */
- if (nss.image)
- XtFree((char *)nss.image);
- nss.image = (union sp *)XtCalloc(sizeof(union sp),
- maxROWS * maxCOLS);
- if (temp_image)
- XtFree((char *)temp_image);
- temp_image = (union sp *)XtCalloc(sizeof(union sp),
- maxROWS*maxCOLS);
-
- /* render_text buffers */
- if (rt_buf8 != (unsigned char *)CN)
- XtFree((char *)rt_buf8);
- rt_buf8 = (unsigned char *)XtMalloc(maxCOLS);
- if (rt_buf16 != (XChar2b *)NULL)
- XtFree((char *)rt_buf16);
- rt_buf16 = (XChar2b *)XtMalloc(maxCOLS * sizeof(XChar2b));
- } else
- (void) memset((char *) nss.image, 0,
- sizeof(union sp) * maxROWS * maxCOLS);
-
- /* Set up a container for the menubar, screen and keypad */
-
- if (cmask & (FONT_CHANGE | MODEL_CHANGE)) {
- nss.screen_width = SCREEN_WIDTH(ss->char_width);
- nss.screen_height = SCREEN_HEIGHT(ss->char_height);
- }
-
- if (toggled(SCROLL_BAR))
- scrollbar_width = SCROLLBAR_WIDTH;
- else
- scrollbar_width = 0;
- container_width = cwidth_nkp = nss.screen_width+2 + scrollbar_width;
- #if defined(X3270_KEYPAD) /*[*/
- mkw = min_keypad_width();
- if (kp_placement == kp_integral && container_width < mkw) {
- keypad_xwidth = mkw - container_width;
- container_width = mkw;
- } else
- keypad_xwidth = 0;
- #endif /*]*/
-
- if (container == (Widget)NULL) {
- container = XtVaCreateManagedWidget(
- "container", huskWidgetClass, toplevel,
- XtNborderWidth, 0,
- XtNwidth, container_width,
- XtNheight, 10,
- /* XXX -- a temporary lie to make Xt happy */
- NULL);
- save_00translations(container, &container_t00);
- set_translations(container, (XtTranslations *)NULL,
- &container_t0);
- if (appres.mono)
- XtVaSetValues(container, XtNbackgroundPixmap, gray,
- NULL);
- else
- XtVaSetValues(container, XtNbackground, keypadbg_pixel,
- NULL);
- }
-
- /* Initialize the menu bar and integral keypad */
-
- #if defined(X3270_KEYPAD) /*[*/
- cwidth_curr = appres.keypad_on ? container_width : cwidth_nkp;
- #else /*][*/
- cwidth_curr = container_width;
- #endif /*]*/
- menubar_height = menubar_qheight(cwidth_curr);
- menubar_init(container, container_width, cwidth_curr);
-
- container_height = menubar_height + nss.screen_height+2;
- #if defined(X3270_KEYPAD) /*[*/
- if (kp_placement == kp_integral) {
- (void) keypad_init(container, container_height,
- container_width, False, False);
- keypad_height = keypad_qheight();
- } else
- keypad_height = 0;
- container_height += keypad_height;
- #endif /*]*/
-
- /* Create screen and set container dimensions */
- inflate_screen();
-
- /* Create scrollbar */
- scrollbar_init((cmask & MODEL_CHANGE) != 0);
-
- XtRealizeWidget(toplevel);
- nss.window = XtWindow(nss.widget);
- set_mcursor();
-
- /* Reinitialize the active icon. */
- aicon_reinit(cmask);
-
- /* Reinitialize the status line. */
- status_reinit(cmask);
-
- cursor_changed = True;
-
- line_changed = True;
-
- /* Redraw the screen. */
- action_internal(PA_Expose_action, IA_REDRAW, CN, CN);
- }
-
-
- static void
- set_toplevel_sizes(void)
- {
- Dimension tw, th;
-
- #if defined(X3270_KEYPAD) /*[*/
- tw = container_width - (appres.keypad_on ? 0 : keypad_xwidth);
- th = container_height - (appres.keypad_on ? 0 : keypad_height);
- #else /*][*/
- tw = container_width;
- th = container_height;
- #endif /*]*/
- XtVaSetValues(toplevel,
- XtNwidth, tw,
- XtNheight, th,
- NULL);
- if (!appres.allow_resize)
- XtVaSetValues(toplevel,
- XtNbaseWidth, tw,
- XtNbaseHeight, th,
- XtNminWidth, tw,
- XtNminHeight, th,
- XtNmaxWidth, tw,
- XtNmaxHeight, th,
- NULL);
- XtVaSetValues(container,
- XtNwidth, container_width,
- XtNheight, container_height,
- NULL);
- main_width = tw;
- main_height = th;
-
- /*
- * Start a timer ticking, in case the window manager doesn't approve
- * of the change.
- */
- if (configure_ticking)
- XtRemoveTimeOut(configure_id);
- configure_id = XtAppAddTimeOut(appcontext, 500, configure_stable, 0);
- configure_ticking = True;
-
- keypad_move();
- }
-
- static void
- inflate_screen(void)
- {
- /* Create the screen window */
- if (nss.widget == NULL) {
- nss.widget = XtVaCreateManagedWidget(
- "screen", widgetClass, container,
- XtNwidth, nss.screen_width,
- XtNheight, nss.screen_height,
- XtNx,
- #if defined(X3270_KEYPAD) /*[*/
- appres.keypad_on ? (keypad_xwidth / 2) : 0,
- #else /*][*/
- 0,
- #endif /*]*/
- XtNy, menubar_height,
- XtNbackground,
- appres.mono ? appres.background : colorbg_pixel,
- NULL);
- save_00translations(nss.widget, &screen_t00);
- set_translations(nss.widget, (XtTranslations *)NULL,
- &screen_t0);
- } else {
- XtVaSetValues(nss.widget,
- XtNwidth, nss.screen_width,
- XtNheight, nss.screen_height,
- XtNx,
- #if defined(X3270_KEYPAD) /*[*/
- appres.keypad_on ? (keypad_xwidth / 2) : 0,
- #else /*][*/
- 0,
- #endif /*]*/
- XtNy, menubar_height,
- XtNbackground,
- appres.mono ? appres.background : colorbg_pixel,
- NULL);
- }
-
- /* Set the container and toplevel dimensions */
- XtVaSetValues(container,
- XtNwidth, container_width,
- XtNheight, container_height,
- NULL);
-
- set_toplevel_sizes();
- }
-
- /* Scrollbar support. */
- void
- screen_set_thumb(float top, float shown)
- {
- if (toggled(SCROLL_BAR))
- XawScrollbarSetThumb(scrollbar, top, shown);
- }
-
- static void
- screen_scroll_proc(Widget w unused, XtPointer client_data unused,
- XtPointer position)
- {
- scroll_proc((int)position, (int)nss.screen_height);
- }
-
- static void
- screen_jump_proc(Widget w unused, XtPointer client_data unused,
- XtPointer percent_ptr)
- {
- jump_proc(*(float *)percent_ptr);
- }
-
- /* Create, move, or reset the scrollbar. */
- static void
- scrollbar_init(Boolean is_reset)
- {
- if (!scrollbar_width) {
- if (scrollbar != (Widget)NULL)
- XtUnmapWidget(scrollbar);
- } else {
- if (scrollbar == (Widget)NULL) {
- scrollbar = XtVaCreateManagedWidget(
- "scrollbar", scrollbarWidgetClass,
- container,
- XtNx, nss.screen_width+1
- #if defined(X3270_KEYPAD) /*[*/
- + (appres.keypad_on ? (keypad_xwidth / 2) : 0)
- #endif /*]*/
- ,
- XtNy, menubar_height,
- XtNwidth, scrollbar_width-1,
- XtNheight, nss.screen_height,
- XtNbackground, appres.mono ?
- appres.background : keypadbg_pixel,
- NULL);
- XtAddCallback(scrollbar, XtNscrollProc,
- screen_scroll_proc, NULL);
- XtAddCallback(scrollbar, XtNjumpProc,
- screen_jump_proc, NULL);
- } else {
- XtVaSetValues(scrollbar,
- XtNx, nss.screen_width+1
- #if defined(X3270_KEYPAD) /*[*/
- + (appres.keypad_on ? (keypad_xwidth / 2) : 0)
- #endif /*]*/
- ,
- XtNy, menubar_height,
- XtNwidth, scrollbar_width-1,
- XtNheight, nss.screen_height,
- XtNbackground, appres.mono ?
- appres.background : keypadbg_pixel,
- NULL);
- XtMapWidget(scrollbar);
- }
- XawScrollbarSetThumb(scrollbar, 0.0, 1.0);
-
- }
-
- /*
- * If the screen dimensions have changed, reallocate the scroll
- * save area.
- */
- if (is_reset || !scroll_initted)
- scroll_init();
- else
- rethumb();
- }
-
- /* Turn the scrollbar on or off */
- void
- toggle_scrollBar(struct toggle *t unused, enum toggle_type tt unused)
- {
- scrollbar_changed = True;
-
- if (toggled(SCROLL_BAR)) {
- scrollbar_width = SCROLLBAR_WIDTH;
- screen_redo = REDO_SCROLLBAR;
- } else {
- scroll_to_bottom();
- scrollbar_width = 0;
- }
-
- screen_reinit(SCROLL_CHANGE);
- if (toggled(SCROLL_BAR))
- rethumb();
- }
-
- /*
- * Called when a host connects, disconnects or changes ANSI/3270 mode.
- */
- static void
- screen_connect(Boolean ignored unused)
- {
- if (!screen_buf)
- return; /* too soon */
-
- if (CONNECTED) {
- ctlr_erase(True);
- if (IN_3270)
- scroll_round();
- cursor_on();
- schedule_cursor_blink();
- } else {
- if (appres.disconnect_clear)
- ctlr_erase(True);
- (void) cursor_off();
- }
-
- mcursor_normal();
- }
-
- /*
- * Mouse cursor changes
- */
-
- static void
- set_mcursor(void)
- {
- switch (mcursor_state) {
- case LOCKED:
- XDefineCursor(display, nss.window, appres.locked_mcursor);
- break;
- case NORMAL:
- XDefineCursor(display, nss.window, appres.normal_mcursor);
- break;
- case WAIT:
- XDefineCursor(display, nss.window, appres.wait_mcursor);
- break;
- }
- lock_icon(mcursor_state);
- }
-
- void
- mcursor_normal(void)
- {
- if (CONNECTED)
- mcursor_state = NORMAL;
- else if (HALF_CONNECTED)
- mcursor_state = WAIT;
- else
- mcursor_state = LOCKED;
- set_mcursor();
- }
-
- void
- mcursor_waiting(void)
- {
- mcursor_state = WAIT;
- set_mcursor();
- }
-
- void
- mcursor_locked(void)
- {
- mcursor_state = LOCKED;
- set_mcursor();
- }
-
- #if defined(X3270_KEYPAD) /*[*/
- /*
- * Called from the keypad button to expose or hide the integral keypad.
- */
- void
- screen_showikeypad(Boolean on)
- {
- if (on)
- screen_redo = REDO_KEYPAD;
-
- inflate_screen();
- if (keypad_xwidth > 0) {
- if (scrollbar != (Widget) NULL)
- scrollbar_init(False);
- menubar_resize(on ? container_width : cwidth_nkp);
- }
- }
- #endif /*]*/
-
-
- /*
- * The host just wrote a blinking character; make sure it blinks
- */
- void
- blink_start(void)
- {
- text_blinkers_exist = True;
- if (!text_blink_scheduled) {
- /* Start in "on" state and start first iteration */
- text_blinking_on = True;
- schedule_text_blink();
- }
- }
-
- /*
- * Restore blanked blinking text
- */
- static void
- text_blink_it(XtPointer closure unused, XtIntervalId *id unused)
- {
- /* Flip the state. */
- text_blinking_on = !text_blinking_on;
-
- /* Force a screen redraw. */
- ctlr_changed(0, ROWS*COLS);
-
- /* If there is still blinking text, schedule the next iteration */
- if (text_blinkers_exist)
- schedule_text_blink();
- else
- text_blink_scheduled = False;
- }
-
- /*
- * Schedule an event to restore blanked blinking text
- */
- static void
- schedule_text_blink(void)
- {
- text_blink_scheduled = True;
- text_blink_id = XtAppAddTimeOut(appcontext, 500, text_blink_it, 0);
- }
-
-
- /*
- * Make the (displayed) cursor disappear. Returns a Boolean indiciating if
- * the cursor was on before the call.
- */
- static Boolean
- cursor_off(void)
- {
- if (cursor_displayed) {
- cursor_displayed = False;
- put_cursor(ss->cursor_daddr, False);
- return True;
- } else
- return False;
- }
-
-
-
- /*
- * Blink the cursor
- */
- static void
- cursor_blink_it(XtPointer closure unused, XtIntervalId *id unused)
- {
- cursor_blink_pending = False;
- if (!CONNECTED || !toggled(CURSOR_BLINK))
- return;
- if (cursor_displayed) {
- if (in_focus)
- (void) cursor_off();
- } else
- cursor_on();
- schedule_cursor_blink();
- }
-
- /*
- * Schedule a cursor blink
- */
- static void
- schedule_cursor_blink(void)
- {
- if (!toggled(CURSOR_BLINK) || cursor_blink_pending)
- return;
- cursor_blink_pending = True;
- cursor_blink_id = XtAppAddTimeOut(appcontext, 500, cursor_blink_it, 0);
- }
-
- /*
- * Cancel a cursor blink
- */
- static void
- cancel_blink(void)
- {
- if (cursor_blink_pending) {
- XtRemoveTimeOut(cursor_blink_id);
- cursor_blink_pending = False;
- }
- }
-
- /*
- * Toggle cursor blinking (called from menu)
- */
- void
- toggle_cursorBlink(struct toggle *t unused, enum toggle_type tt unused)
- {
- if (!CONNECTED)
- return;
-
- if (toggled(CURSOR_BLINK))
- schedule_cursor_blink();
- else
- cursor_on();
- }
-
- /*
- * Make the cursor visible at its (possibly new) location.
- */
- static void
- cursor_on(void)
- {
- if (cursor_enabled && !cursor_displayed) {
- cursor_displayed = True;
- put_cursor(cursor_addr, True);
- ss->cursor_daddr = cursor_addr;
- cursor_changed = False;
- }
- }
-
-
- /*
- * Toggle the cursor (block/underline).
- */
- void
- toggle_altCursor(struct toggle *t, enum toggle_type tt unused)
- {
- Boolean was_on;
-
- /* do_toggle already changed the value; temporarily change it back */
- toggle_toggle(t);
-
- was_on = cursor_off();
-
- /* Now change it back again */
- toggle_toggle(t);
-
- if (was_on)
- cursor_on();
- }
-
-
- /*
- * Move the cursor to the specified buffer address.
- */
- void
- cursor_move(int baddr)
- {
- cursor_addr = baddr;
- cursor_pos();
- }
-
- /*
- * Display the cursor position on the status line
- */
- static void
- cursor_pos(void)
- {
- if (!toggled(CURSOR_POS) || !CONNECTED)
- return;
- status_cursor_pos(cursor_addr);
- }
-
- /*
- * Toggle the display of the cursor position
- */
- void
- toggle_cursorPos(struct toggle *t unused, enum toggle_type tt unused)
- {
- if (toggled(CURSOR_POS))
- cursor_pos();
- else
- status_uncursor_pos();
- }
-
- /*
- * Enable or disable cursor display (used by scroll logic)
- */
- void
- enable_cursor(Boolean on)
- {
- if ((cursor_enabled = on) && CONNECTED) {
- cursor_on();
- cursor_changed = True;
- } else
- (void) cursor_off();
- }
-
-
- /*
- * Redraw the screen.
- */
- static void
- do_redraw(Widget w, XEvent *event, String *params unused,
- Cardinal *num_params unused)
- {
- int x, y, width, height;
- int startcol, ncols;
- int startrow, endrow, row;
- register int i;
- int c0;
-
- if (w == nss.widget) {
- keypad_first_up();
- if (appres.active_icon && iconic) {
- ss = &nss;
- iconic = False;
- }
- } else if (appres.active_icon && w == iss.widget) {
- if (appres.active_icon && !iconic) {
- ss = &iss;
- iconic = True;
- }
- } else if (event)
- return;
-
- /* Only redraw as necessary for an expose event */
- if (event && event->type == Expose) {
- ss->exposed_yet = True;
- x = event->xexpose.x;
- y = event->xexpose.y;
- width = event->xexpose.width;
- height = event->xexpose.height;
- startrow = ssY_TO_ROW(y);
- if (startrow < 0)
- startrow = 0;
- if (startrow > 0)
- startrow--;
- endrow = ssY_TO_ROW(y+height);
- endrow = endrow >= maxROWS ? maxROWS : endrow + 1;
- startcol = ssX_TO_COL(x);
- if (startcol < 0)
- startcol = 0;
- if (startcol > 0)
- startcol--;
- ncols = ssX_TO_COL(width+ss->char_width) + 2;
- while ((ROWCOL_TO_BA(startrow, startcol) % maxCOLS) + ncols > maxCOLS)
- ncols--;
- for (row = startrow; row < endrow; row++) {
- (void) memset((char *) &ss->image[ROWCOL_TO_BA(row, startcol)],
- 0, ncols * sizeof(union sp));
- if (ss->debugging_font) {
- c0 = ROWCOL_TO_BA(row, startcol);
-
- for (i = 0; i < ncols; i++)
- ss->image[c0 + i].bits.cg = CG_space;
- }
- }
-
- } else {
- XFillRectangle(display, ss->window,
- get_gc(ss, INVERT_COLOR(0)),
- 0, 0, ss->screen_width, ss->screen_height);
- (void) memset((char *) ss->image, 0,
- (maxROWS*maxCOLS) * sizeof(union sp));
- if (ss->debugging_font)
- for (i = 0; i < maxROWS*maxCOLS; i++)
- ss->image[i].bits.cg = CG_space;
- ss->copied = False;
- }
- ctlr_changed(0, ROWS*COLS);
- cursor_changed = True;
- if (!appres.active_icon || !iconic) {
- line_changed = True;
- status_touch();
- }
- }
-
- /*
- * Explicitly redraw the screen (invoked from the keyboard).
- */
- void
- Redraw_action(Widget w, XEvent *event, String *params, Cardinal *num_params)
- {
- action_debug(Redraw_action, event, params, num_params);
- do_redraw(w, event, params, num_params);
- }
-
- /*
- * Implicitly redraw the screen (triggered by Expose events).
- */
- void
- PA_Expose_action(Widget w, XEvent *event, String *params, Cardinal *num_params)
- {
- #if defined(INTERNAL_ACTION_DEBUG) /*[*/
- action_debug(PA_Expose_action, event, params, num_params);
- #endif /*]*/
- do_redraw(w, event, params, num_params);
- }
-
-
- /*
- * Redraw the changed parts of the screen.
- */
-
- void
- screen_disp(void)
- {
-
- /* No point in doing anything if we aren't visible yet. */
- if (!ss->exposed_yet)
- return;
-
- /*
- * We don't set "cursor_changed" when the host moves the cursor,
- * 'cause he might just move it back later. Set it here if the cursor
- * has moved since the last call to screen_disp.
- */
- if (cursor_addr != ss->cursor_daddr)
- cursor_changed = True;
-
- /*
- * If only the cursor has changed (and not the screen image), draw it.
- */
- if (cursor_changed && !screen_changed) {
- if (cursor_off())
- cursor_on();
- }
-
- /*
- * Redraw the parts of the screen that need refreshing, and redraw the
- * cursor if necessary.
- */
- if (screen_changed) {
- Boolean was_on = False;
-
- /* Draw the new screen image into "temp_image" */
- if (screen_changed)
- draw_fields(temp_image, first_changed, last_changed);
-
- /* Set "cursor_changed" if the text under it has changed. */
- if (ss->image[fl_baddr(cursor_addr)].word !=
- temp_image[fl_baddr(cursor_addr)].word)
- cursor_changed = True;
-
- /* Undraw the cursor, if necessary. */
- if (cursor_changed)
- was_on = cursor_off();
-
- /* Intelligently update the X display with the new text. */
- resync_display(temp_image, first_changed, last_changed);
-
- /* Redraw the cursor. */
- if (was_on)
- cursor_on();
-
- screen_changed = False;
- first_changed = -1;
- last_changed = -1;
- }
-
- if (!appres.active_icon || !iconic) {
- /* Refresh the status line. */
- status_disp();
-
- /* Refresh the line across the bottom of the screen. */
- if (line_changed) {
- XDrawLine(display, ss->window,
- get_gc(ss, GC_NONDEFAULT | DEFAULT_PIXEL),
- 0,
- ssROW_TO_Y(maxROWS-1)+SGAP-1,
- ssCOL_TO_X(maxCOLS)+HHALO,
- ssROW_TO_Y(maxROWS-1)+SGAP-1);
- line_changed = False;
- }
- }
- draw_aicon_label();
- }
-
-
- /*
- * Render a blank rectangle on the X display.
- */
- static void
- render_blanks(int baddr, int height, union sp *buffer)
- {
- int x, y;
-
- #if defined(_ST) /*[*/
- (void) printf("render_blanks(baddr=%s, height=%d)\n", rcba(baddr),
- height);
- #endif /*]*/
-
- x = ssCOL_TO_X(BA_TO_COL(baddr));
- y = ssROW_TO_Y(BA_TO_ROW(baddr));
-
- XFillRectangle(display, ss->window,
- get_gc(ss, INVERT_COLOR(0)),
- x, y - ss->ascent,
- (ss->char_width * COLS) + 1, (ss->char_height * height));
-
- (void) memmove(&ss->image[baddr], &buffer[baddr],
- COLS * height *sizeof(union sp));
- }
-
- /*
- * Check if a region of the screen is effectively empty: all blanks or nulls
- * with no extended highlighting attributes and not selected.
- *
- * Works _only_ with non-debug fonts.
- */
- static Boolean
- empty_space(register union sp *buffer, int len)
- {
- register int i;
-
- for (i = 0; i < len; i++, buffer++) {
- if (buffer->bits.gr ||
- buffer->bits.sel ||
- (buffer->bits.fg & INVERT_MASK) ||
- !BKM_ISSET(buffer->bits.cg))
- return False;
- }
- return True;
- }
-
-
- /*
- * Reconcile the differences between a region of 'buffer' (what we want on
- * the X display) and ss->image[] (what is on the X display now). The region
- * must not span lines.
- */
- static void
- resync_text(int baddr, int len, union sp *buffer)
- {
- static Boolean ever = False;
- static unsigned long cmask = 0L;
- static unsigned long gmask = 0L;
-
- #if defined(_ST) /*[*/
- (void) printf("resync_text(baddr=%s, len=%d)\n", rcba(baddr), len);
- #endif /*]*/
- if (!ever) {
- union sp b;
-
- /* Create masks for the "important" fields in an sp. */
- b.word = 0L;
- b.bits.fg = COLOR_MASK | INVERT_MASK;
- b.bits.sel = 1;
- b.bits.gr = GR_UNDERLINE | GR_INTENSIFY;
- cmask = b.word;
-
- b.word = 0L;
- b.bits.fg = INVERT_MASK;
- b.bits.sel = 1;
- b.bits.gr = 0xf;
- gmask = b.word;
-
- ever = True;
- }
-
- if (!ss->debugging_font &&
- len > 1 &&
- empty_space(&buffer[baddr], len)) {
- int x, y;
-
- x = ssCOL_TO_X(BA_TO_COL(baddr));
- y = ssROW_TO_Y(BA_TO_ROW(baddr));
-
- /* All empty, fill a rectangle */
- #if defined(_ST) /*[*/
- (void) printf("FillRectangle(baddr=%s, len=%d)\n", rcba(baddr),
- len);
- #endif /*]*/
- XFillRectangle(display, ss->window,
- get_gc(ss, INVERT_COLOR(0)),
- x, y - ss->ascent,
- (ss->char_width * len) + 1, ss->char_height);
- } else {
- unsigned long attrs, attrs2;
- Boolean has_gr, has_gr2;
- Boolean empty, empty2;
- union sp ra;
- int i;
- int i0 = 0;
-
- ra = buffer[baddr];
-
- /* Note the characteristics of the beginning of the region. */
- attrs = buffer[baddr].word & cmask;
- has_gr = (buffer[baddr].word & gmask) != 0;
- empty = !has_gr && BKM_ISSET(buffer[baddr].bits.cg);
-
- for (i = 0; i < len; i++) {
- /* Note the characteristics of this character. */
- attrs2 = buffer[baddr+i].word & cmask;
- has_gr2 = (buffer[baddr+i].word & gmask) != 0;
- empty2 = !has_gr2 && BKM_ISSET(buffer[baddr+i].bits.cg);
-
- /* If this character has exactly the same attributes
- as the current region, simply add it, noting that
- the region might now not be empty. */
- if (attrs2 == attrs) {
- if (!empty2)
- empty = 0;
- continue;
- }
-
- /* If this character is empty, and the current region
- has no GR attributes, pretend it matches. */
- if (empty2 && !has_gr)
- continue;
-
- /* If the current region is empty, this character
- isn't empty, and this character has no GR
- attributes, change the current region's attributes
- to this character's attributes and add it. */
- if (empty && !empty2 && !has_gr2) {
- attrs = attrs2;
- has_gr = has_gr2;
- empty = empty2;
- ra = buffer[baddr+i];
- continue;
- }
-
- /* Dump the region and start a new one with this
- character. */
- render_text(&buffer[baddr+i0], baddr+i0, i - i0, False,
- &ra);
- attrs = attrs2;
- has_gr = has_gr2;
- empty = empty2;
- i0 = i;
- ra = buffer[baddr+i];
- }
-
- /* Dump the remainder of the region. */
- render_text(&buffer[baddr+i0], baddr+i0, len - i0, False, &ra);
- }
-
- /* The X display is now correct; update ss->image[]. */
- (void) memmove(&ss->image[baddr], &buffer[baddr], len*sizeof(union sp));
- }
-
- /*
- * Render text onto the X display. The region must not span lines.
- */
- static void
- render_text(union sp *buffer, int baddr, int len, Boolean block_cursor,
- union sp *attrs)
- {
- int color;
- int x, y;
- GC dgc;
- int sel = attrs->bits.sel;
- register int i;
-
- #if defined(_ST) /*[*/
- (void) printf("render_text(baddr=%s, len=%d)\n", rcba(baddr), len);
- #endif /*]*/
-
- if (ss->standard_font) { /* Standard X font */
- register unsigned char *xfmap = ss->xfmap;
-
- if (toggled(MONOCASE)) {
- for (i = 0; i < len; i++) {
- switch (buffer[i].bits.cs) {
- case 0:
- rt_buf8[i] =
- asc2uc[xfmap[buffer[i].bits.cg]];
- break;
- case 1:
- rt_buf8[i] = ge2asc[buffer[i].bits.cg];
- break;
- case 2:
- rt_buf8[i] = buffer[i].bits.cg;
- break;
- }
- }
- } else for (i = 0; i < len; i++) {
- switch (buffer[i].bits.cs) {
- case 0:
- rt_buf8[i] = xfmap[buffer[i].bits.cg];
- break;
- case 1:
- rt_buf8[i] = ge2asc[buffer[i].bits.cg];
- break;
- case 2:
- rt_buf8[i] = buffer[i].bits.cg;
- break;
- }
- }
- } else if (ss->extended_3270font) { /* 16-bit (new) x3270 font */
- if (toggled(MONOCASE)) {
- for (i = 0; i < len; i++) {
- rt_buf16[i].byte1 = buffer[i].bits.cs;
- switch (buffer[i].bits.cs) {
- case 0:
- rt_buf16[i].byte2 =
- cg2uc[buffer[i].bits.cg];
- break;
- case 1:
- case 2:
- rt_buf16[i].byte2 = buffer[i].bits.cg;
- break;
- }
- }
- } else
- for (i = 0; i < len; i++) {
- rt_buf16[i].byte1 = buffer[i].bits.cs;
- rt_buf16[i].byte2 = buffer[i].bits.cg;
- }
- } else { /* 8-bit (old) x3270 font */
- if (toggled(MONOCASE)) {
- for (i = 0; i < len; i++) {
- switch (buffer[i].bits.cs) {
- case 0:
- rt_buf8[i] =
- cg2uc[buffer[i].bits.cg];
- break;
- case 1:
- rt_buf8[i] =
- ge2cg8[buffer[i].bits.cg];
- break;
- case 2:
- rt_buf8[i] = CG_boxsolid;
- break;
- }
- }
- } else
- for (i = 0; i < len; i++) {
- switch (buffer[i].bits.cs) {
- case 0:
- rt_buf8[i] = buffer[i].bits.cg;
- break;
- case 1:
- rt_buf8[i] =
- ge2cg8[buffer[i].bits.cg];
- break;
- case 2:
- rt_buf8[i] = CG_boxsolid;
- break;
- }
- }
- }
-
- x = ssCOL_TO_X(BA_TO_COL(baddr));
- y = ssROW_TO_Y(BA_TO_ROW(baddr));
- color = attrs->bits.fg;
-
- /* Draw. */
- if (sel && !block_cursor) {
- if (!appres.mono)
- dgc = get_selgc(ss, color);
- else
- dgc = get_gc(ss, INVERT_COLOR(color));
- } else if (block_cursor && !(appres.mono && sel)) {
- if (appres.use_cursor_color)
- dgc = ss->invucgc;
- else
- dgc = get_gc(ss, INVERT_COLOR(color));
- } else
- dgc = get_gc(ss, color);
-
- /* Draw the text */
- if (ss->extended_3270font)
- XDrawImageString16(display, ss->window, dgc, x, y, rt_buf16,
- len);
- else
- XDrawImageString(display, ss->window, dgc, x, y,
- (char *)rt_buf8, len);
- if (ss->overstrike &&
- ((attrs->bits.gr & GR_INTENSIFY) ||
- ((appres.mono || (!appres.m3279 && appres.highlight_bold)) &&
- ((color & BASE_MASK) == FA_INT_HIGH_SEL)))) {
- if (ss->extended_3270font)
- XDrawString16(display, ss->window, dgc, x+1, y,
- rt_buf16, len);
- else
- XDrawString(display, ss->window, dgc, x+1, y,
- (char *)rt_buf8, len);
- }
- if (attrs->bits.gr & GR_UNDERLINE)
- XDrawLine(display,
- ss->window,
- dgc,
- x,
- y - ss->ascent + ss->char_height - 1,
- x + ss->char_width * len,
- y - ss->ascent + ss->char_height - 1);
- }
-
-
- #if defined(X3270_ANSI) /*[*/
- Boolean
- screen_obscured(void)
- {
- return ss->obscured;
- }
-
- /*
- * Scroll the screen image one row.
- *
- * This is the optimized path from ctlr_scroll(); it assumes that
- * screen_buf[] and ea_buf[] have already been modified and that the screen
- * can be brought into sync by hammering ss->image and the bitmap.
- */
- void
- screen_scroll(void)
- {
- Boolean was_on;
-
- if (!ss->exposed_yet)
- return;
-
- was_on = cursor_off();
- (void) memmove(&ss->image[0], &ss->image[COLS],
- (ROWS - 1) * COLS * sizeof(union sp));
- (void) memmove(&temp_image[0], &temp_image[COLS],
- (ROWS - 1) * COLS * sizeof(union sp));
- (void) memset((char *)&ss->image[(ROWS - 1) * COLS], 0,
- COLS * sizeof(union sp));
- (void) memset((char *)&temp_image[(ROWS - 1) * COLS], 0,
- COLS * sizeof(union sp));
- XCopyArea(display, ss->window, ss->window, get_gc(ss, 0),
- ssCOL_TO_X(0),
- ssROW_TO_Y(1) - ss->ascent,
- ss->char_width * COLS,
- ss->char_height * (ROWS - 1),
- ssCOL_TO_X(0),
- ssROW_TO_Y(0) - ss->ascent);
- ss->copied = True;
- XFillRectangle(display, ss->window, get_gc(ss, INVERT_COLOR(0)),
- ssCOL_TO_X(0),
- ssROW_TO_Y(ROWS - 1) - ss->ascent,
- (ss->char_width * COLS) + 1,
- ss->char_height);
- if (was_on)
- cursor_on();
- }
- #endif /*]*/
-
-
- /*
- * Toggle mono-/dual-case mode.
- */
- void
- toggle_monocase(struct toggle *t unused, enum toggle_type tt unused)
- {
- (void) memset((char *) ss->image, 0,
- (ROWS*COLS) * sizeof(union sp));
- ctlr_changed(0, ROWS*COLS);
- }
-
- /*
- * Toggle screen flip
- */
- void
- screen_flip(void)
- {
- flipped = !flipped;
-
- action_internal(PA_Expose_action, IA_REDRAW, CN, CN);
- }
-
- /*
- * "Draw" screen_buf into a buffer
- */
- static void
- draw_fields(union sp *buffer, int first, int last)
- {
- int baddr = 0;
- unsigned char *fap;
- unsigned char fa;
- struct ea *field_ea;
- struct ea *char_ea = ea_buf;
- unsigned char *sbp = screen_buf;
- int field_color;
- int zero;
- Boolean any_blink = False;
-
- /* If there is any blinking text, override the suggested boundaries. */
- if (text_blinkers_exist) {
- first = -1;
- last = -1;
- }
-
- /* Adjust pointers to start of region. */
- if (first > 0) {
- baddr += first;
- char_ea += first;
- sbp += first;
- buffer += first;
- }
- fap = get_field_attribute(baddr);
- fa = *fap;
- field_ea = fa2ea(fap);
-
- /* Adjust end of region. */
- if (last == -1 || last >= ROWS*COLS)
- last = 0;
-
- zero = FA_IS_ZERO(fa);
- if (field_ea->fg && (!appres.modified_sel || !FA_IS_MODIFIED(fa)))
- field_color = field_ea->fg & COLOR_MASK;
- else
- field_color = fa_color(fa);
-
- do {
- unsigned char c = *sbp;
- union sp b;
-
- b.word = 0; /* clear out all fields */
-
- if (IS_FA(c)) {
- fa = c;
- field_ea = char_ea;
- zero = FA_IS_ZERO(fa);
- if (field_ea->fg && (!appres.modified_sel || !FA_IS_MODIFIED(fa)))
- field_color = field_ea->fg & COLOR_MASK;
- else
- field_color = fa_color(fa);
- if (ss->debugging_font) {
- b.bits.cg = c;
- if (appres.m3279 || !zero)
- b.bits.fg = field_color;
- } /* otherwise, CG_null in color 0 */
- } else {
- unsigned short gr;
- int e_color;
-
- /* Find the right graphic rendition. */
- gr = char_ea->gr;
- if (!gr)
- gr = field_ea->gr;
- if (gr & GR_BLINK)
- any_blink = True;
- if (appres.highlight_bold && FA_IS_HIGH(fa))
- gr |= GR_INTENSIFY;
-
- /* Find the right color. */
- if (char_ea->fg)
- e_color = char_ea->fg & COLOR_MASK;
- else if (appres.mono && (gr & GR_INTENSIFY))
- e_color = fa_color(FA_INT_HIGH_SEL);
- else
- e_color = field_color;
- if (gr & GR_REVERSE)
- e_color = INVERT_COLOR(e_color);
- if (!appres.mono)
- b.bits.fg = e_color;
-
- /* Find the right character and character set. */
- if (zero) {
- if (ss->debugging_font)
- b.bits.cg = CG_space;
- } else if ((c != CG_null && c != CG_space) ||
- (gr & (GR_REVERSE | GR_UNDERLINE)) ||
- ss->debugging_font) {
-
- b.bits.fg = e_color;
-
- /*
- * Replace blanked-out blinking text with
- * spaces.
- */
- if (!text_blinking_on && (gr & GR_BLINK))
- b.bits.cg = CG_space;
- else {
- b.bits.cg = c;
- if (char_ea->cs)
- b.bits.cs = char_ea->cs;
- else
- b.bits.cs = field_ea->cs;
- if (b.bits.cs & CS_GE)
- b.bits.cs = 1;
- else
- b.bits.cs &= CS_MASK;
- }
-
- } /* otherwise, CG_null */
-
- b.bits.gr = gr & (GR_UNDERLINE | GR_INTENSIFY);
- }
- if (SELECTED(baddr))
- b.bits.sel = 1;
- if (!flipped)
- *buffer++ = b;
- else
- *(buffer + fl_baddr(baddr)) = b;
- char_ea++;
- sbp++;
- INC_BA(baddr);
- } while (baddr != last);
-
- /* Cancel blink timeouts if none were seen this pass. */
- if (!any_blink)
- text_blinkers_exist = False;
- }
-
-
- /*
- * Resync the X display with the contents of 'buffer'
- */
- static void
- resync_display(union sp *buffer, int first, int last)
- {
- register int i, j;
- int b = 0;
- int i0 = -1;
- Boolean ccheck;
- int fca = fl_baddr(cursor_addr);
- int first_row, last_row;
- # define SPREAD 10
-
- if (first < 0) {
- first_row = 0;
- last_row = ROWS;
- } else {
- first_row = first / COLS;
- b = first_row * COLS;
- last_row = (last + (COLS-1)) / COLS;
- }
-
- for (i = first_row; i < last_row; b += COLS, i++) {
- int d0 = -1;
- int s0 = -1;
-
- /* Has the line changed? */
- if (!memcmp((char *) &ss->image[b], (char *) &buffer[b],
- COLS*sizeof(union sp))) {
- if (i0 >= 0) {
- render_blanks(i0 * COLS, i - i0, buffer);
- i0 = -1;
- }
- continue;
- }
-
- /* Is the new value empty? */
- if (!ss->debugging_font &&
- !(fca >= b && fca < (b+COLS)) &&
- empty_space(&buffer[b], COLS)) {
- if (i0 < 0)
- i0 = i;
- continue;
- }
-
- /* Yes, it changed, and it isn't blank.
- Dump any pending blank lines. */
- if (i0 >= 0) {
- render_blanks(i0 * COLS, i - i0, buffer);
- i0 = -1;
- }
-
- /* New text. Scan it. */
- ccheck = cursor_displayed &&
- fca >= b &&
- fca < (b+COLS);
- for (j = 0; j < COLS; j++) {
- if (ccheck && b+j == fca) {
- /* Don't repaint over the cursor. */
-
- /* Dump any pending "different" characters. */
- if (d0 >= 0)
- resync_text(b+d0, j-d0, buffer);
-
- /* Start over. */
- d0 = -1;
- s0 = -1;
- continue;
- }
- if (ss->image[b+j].word == buffer[b+j].word) {
-
- /* Character is the same. */
-
- if (d0 >= 0) {
- /* Something is pending... */
- if (s0 < 0) {
- /* Start of "same" area */
- s0 = j;
- } else {
- /* nth matching character */
- if (j - s0 > SPREAD) {
- /* too many */
- resync_text(b+d0,
- s0-d0, buffer);
- d0 = -1;
- s0 = -1;
- }
- }
- }
- } else {
-
- /* Character is different. */
-
- /* Forget intermediate matches. */
- s0 = -1;
-
- if (d0 < 0)
- /* Mark the start. */
- d0 = j;
- }
- }
-
- /* Dump any pending "different" characters. */
- if (d0 >= 0)
- resync_text(b+d0, COLS-d0, buffer);
- }
- if (i0 >= 0)
- render_blanks(i0 * COLS, last_row - i0, buffer);
- }
-
-
- /*
- * Support code for cursor redraw.
- */
-
- /*
- * Calculate a flipped baddr.
- */
- static int
- fl_baddr(int baddr)
- {
- if (!flipped)
- return baddr;
- return ((baddr / COLS) * COLS) + (COLS - (baddr % COLS) - 1);
- }
-
- /*
- * Return the proper foreground color for a character position.
- */
-
- static int
- char_color(int baddr)
- {
- unsigned char *fa;
- int color;
-
- fa = get_field_attribute(baddr);
-
- /*
- * Find the color of the character or the field.
- */
- if (ea_buf[baddr].fg)
- color = ea_buf[baddr].fg & COLOR_MASK;
- else if (fa2ea(fa)->fg && (!appres.modified_sel || !FA_IS_MODIFIED(*fa)))
- color = fa2ea(fa)->fg & COLOR_MASK;
- else
- color = fa_color(*fa);
-
- /*
- * Now apply reverse video.
- *
- * One bit of strangeness:
- * If the buffer is a field attribute and we aren't using the
- * debug font, it's displayed as a blank; don't invert.
- */
- if (!((IS_FA(screen_buf[baddr]) && !ss->debugging_font)) &&
- ((ea_buf[baddr].gr & GR_REVERSE) || (fa2ea(fa)->gr & GR_REVERSE)))
- color = INVERT_COLOR(color);
-
- /*
- * In monochrome, apply selection status as well.
- */
- if (appres.mono && SELECTED(baddr))
- color = INVERT_COLOR(color);
-
- return color;
- }
-
-
- /*
- * Select a GC for drawing a hollow or underscore cursor.
- */
- static GC
- cursor_gc(int baddr)
- {
- /*
- * If they say use a particular color, use it.
- */
- if (appres.use_cursor_color)
- return ss->ucgc;
- else
- return get_gc(ss, char_color(baddr));
- }
-
- /*
- * Redraw one character.
- * If 'invert' is true, invert the foreground and background colors.
- */
- static void
- redraw_char(int baddr, Boolean invert)
- {
- union sp buffer;
- unsigned char *fa;
- int gr;
- int blank_it = 0;
-
- if (!invert) {
- int flb = fl_baddr(baddr);
-
- /* Simply put back what belongs there. */
- render_text(&ss->image[flb], flb, 1, False, &ss->image[flb]);
- return;
- }
-
- /*
- * Fabricate the right thing.
- * ss->image isn't going to help, because it may contain shortcuts
- * for faster display, so we have to construct a buffer to use.
- */
- buffer.word = 0L;
- buffer.bits.cg = screen_buf[baddr];
- buffer.bits.cs = ea_buf[baddr].cs;
- if (buffer.bits.cs & CS_GE)
- buffer.bits.cs = 1;
- else
- buffer.bits.cs &= CS_MASK;
- fa = get_field_attribute(baddr);
- gr = ea_buf[baddr].gr;
- if (!gr)
- gr = fa2ea(fa)->gr;
- if (IS_FA(screen_buf[baddr])) {
- if (!ss->debugging_font)
- blank_it = 1;
- } else if (FA_IS_ZERO(*fa)) {
- blank_it = 1;
- } else if (text_blinkers_exist && !text_blinking_on) {
- if (gr & GR_BLINK)
- blank_it = 1;
- }
- if (blank_it) {
- buffer.bits.cg = CG_space;
- buffer.bits.cs = 0;
- }
- buffer.bits.fg = char_color(baddr);
- buffer.bits.gr |= (gr & GR_INTENSIFY);
- render_text(&buffer, fl_baddr(baddr), 1, True, &buffer);
- }
-
- /*
- * Draw a hollow cursor.
- */
- static void
- hollow_cursor(int baddr)
- {
- XDrawRectangle(display,
- ss->window,
- cursor_gc(baddr),
- ssCOL_TO_X(BA_TO_COL(fl_baddr(baddr))),
- ssROW_TO_Y(BA_TO_ROW(baddr)) - ss->ascent +
- (appres.mono ? 1 : 0),
- ss->char_width - 1,
- ss->char_height - (appres.mono ? 2 : 1));
- }
-
- /*
- * Draw an underscore cursor.
- */
- static void
- underscore_cursor(int baddr)
- {
- XDrawRectangle(display,
- ss->window,
- cursor_gc(baddr),
- ssCOL_TO_X(BA_TO_COL(fl_baddr(baddr))),
- ssROW_TO_Y(BA_TO_ROW(baddr)) - ss->ascent +
- ss->char_height - 2,
- ss->char_width - 1,
- 1);
- }
-
- /*
- * Invert a square over a character.
- */
- static void
- small_inv_cursor(int baddr)
- {
- XFillRectangle(display,
- ss->window,
- ss->mcgc,
- ssCOL_TO_X(BA_TO_COL(fl_baddr(baddr))),
- ssROW_TO_Y(BA_TO_ROW(baddr)) - ss->ascent + 1,
- ss->char_width,
- (ss->char_height > 2) ? (ss->char_height - 2) : 1);
- }
-
- /*
- * Draw or remove the cursor.
- */
- static void
- put_cursor(int baddr, Boolean on)
- {
- /*
- * If the cursor is being turned off, simply redraw the text under it.
- */
- if (!on) {
- redraw_char(baddr, False);
- return;
- }
-
- /*
- * If underscore cursor, redraw the character and draw the underscore.
- */
- if (toggled(ALT_CURSOR)) {
- redraw_char(baddr, False);
- underscore_cursor(baddr);
- return;
- }
-
- /*
- * On, and not an underscore.
- *
- * If out of focus, either draw an empty box in its place (if block
- * cursor) or redraw the underscore (if underscore).
- */
- if (!in_focus) {
- hollow_cursor(baddr);
- return;
- }
-
- /*
- * If monochrome, invert a small square over the characters.
- */
- if (appres.mono) {
- small_inv_cursor(baddr);
- return;
- }
-
- /*
- * Color: redraw the character in reverse video.
- */
- redraw_char(baddr, True);
- }
-
-
- /* Allocate a named color. */
- static Boolean
- alloc_color(char *name, enum fallback_color fb_color, Pixel *pixel)
- {
- XColor cell, db;
- Screen *s;
-
- s = XtScreen(toplevel);
-
- if (XAllocNamedColor(display, XDefaultColormapOfScreen(s), name,
- &cell, &db) != 0) {
- *pixel = db.pixel;
- return True;
- }
- switch (fb_color) {
- case FB_WHITE:
- *pixel = XWhitePixelOfScreen(s);
- break;
- case FB_BLACK:
- *pixel = XBlackPixelOfScreen(s);
- break;
- }
- return False;
- }
-
- /* Spell out a fallback color. */
- static const char *
- fb_name(enum fallback_color fb_color)
- {
- switch (fb_color) {
- case FB_WHITE:
- return "white";
- case FB_BLACK:
- return "black";
- }
- return "chartreuse"; /* to keep Gcc -Wall happy */
- }
-
- /* Allocate color pixels. */
- static void
- allocate_pixels(void)
- {
-
- if (appres.mono)
- return;
-
- /* Allocate constant elements. */
- if (!alloc_color(appres.colorbg_name, FB_BLACK, &colorbg_pixel))
- xs_warning("Cannot allocate colormap \"%s\" for screen background, using \"black\"",
- appres.colorbg_name);
- if (!alloc_color(appres.selbg_name, FB_BLACK, &selbg_pixel))
- xs_warning("Cannot allocate colormap \"%s\" for select background, using \"black\"",
- appres.selbg_name);
- if (!alloc_color(appres.keypadbg_name, FB_WHITE, &keypadbg_pixel))
- xs_warning("Cannot allocate colormap \"%s\" for keypad background, using \"white\"",
- appres.keypadbg_name);
- if (appres.use_cursor_color) {
- if (!alloc_color(appres.cursor_color_name, FB_WHITE, &cursor_pixel))
- xs_warning("Cannot allocate colormap \"%s\" for cursor color, using \"white\"",
- appres.cursor_color_name);
- }
-
- /* Allocate pseudocolors. */
- if (!appres.m3279) {
- if (!alloc_color(appres.normal_name, FB_WHITE, &normal_pixel))
- xs_warning("Cannot allocate colormap \"%s\" for text, using \"white\"",
- appres.normal_name);
- if (!alloc_color(appres.select_name, FB_WHITE, &select_pixel))
- xs_warning("Cannot allocate colormap \"%s\" for selectable text, using \"white\"",
- appres.select_name);
- if (!alloc_color(appres.bold_name, FB_WHITE, &bold_pixel))
- xs_warning("Cannot allocate colormap \"%s\" for bold text, using \"white\"",
- appres.bold_name);
- return;
- }
- }
-
- #if defined(X3270_MENUS) /*[*/
- /* Deallocate pixels. */
- static void
- destroy_pixels(void)
- {
- int i;
-
- /*
- * It would make sense to deallocate many of the pixels here, but
- * the only available call (XFreeColors) would deallocate cells
- * that may be in use by other Xt widgets. Occh.
- */
-
- for (i = 0; i < 16; i++)
- cpx_done[i] = False;
- }
- #endif /*]*/
-
- /*
- * Create graphics contexts.
- */
- static void
- make_gcs(struct sstate *s)
- {
- XGCValues xgcv;
-
- if (appres.m3279) {
- int i;
-
- for (i = 0; i < NGCS; i++) {
- if (s->gc[i] != (GC)None) {
- XtReleaseGC(toplevel, s->gc[i]);
- s->gc[i] = (GC)None;
- }
- if (s->gc[i + NGCS] != (GC)None) {
- XtReleaseGC(toplevel, s->gc[i + NGCS]);
- s->gc[i + NGCS] = (GC)None;
- }
- if (s->selgc[i] != (GC)None) {
- XtReleaseGC(toplevel, s->selgc[i]);
- s->selgc[i] = (GC)None;
- }
- }
- } else {
- if (!appres.mono) {
- make_gc_set(s, FA_INT_NORM_NSEL, normal_pixel,
- colorbg_pixel);
- make_gc_set(s, FA_INT_NORM_SEL, select_pixel,
- colorbg_pixel);
- make_gc_set(s, FA_INT_HIGH_SEL, bold_pixel,
- colorbg_pixel);
- } else {
- make_gc_set(s, FA_INT_NORM_NSEL, appres.foreground,
- appres.background);
- make_gc_set(s, FA_INT_NORM_SEL, appres.foreground,
- appres.background);
- make_gc_set(s, FA_INT_HIGH_SEL, appres.foreground,
- appres.background);
- }
- }
-
- /* Create monochrome block cursor GC. */
- if (appres.mono && s->mcgc == (GC)None) {
- if (screen_depth > 1)
- xgcv.function = GXinvert;
- else
- xgcv.function = GXxor;
- xgcv.foreground = 1L;
- s->mcgc = XtGetGC(toplevel,
- GCForeground|GCFunction,
- &xgcv);
- }
-
- /* Create explicit cursor color cursor GCs. */
- if (appres.use_cursor_color) {
- if (s->ucgc != (GC)None) {
- XtReleaseGC(toplevel, s->ucgc);
- s->ucgc = (GC)None;
- }
- xgcv.foreground = cursor_pixel;
- s->ucgc = XtGetGC(toplevel, GCForeground, &xgcv);
-
- if (s->invucgc != (GC)None) {
- XtReleaseGC(toplevel, s->invucgc);
- s->invucgc = (GC)None;
- }
- xgcv.foreground = colorbg_pixel;
- xgcv.background = cursor_pixel;
- xgcv.font = s->fid;
- s->invucgc = XtGetGC(toplevel,
- GCForeground|GCBackground|GCFont, &xgcv);
- }
-
- /* Set the flag for overstriking bold. */
- s->overstrike = (s->char_width > 1);
- }
-
- /* Set up a default color scheme. */
- static void
- default_color_scheme(void)
- {
- static int default_attrib_colors[4] = {
- GC_NONDEFAULT | COLOR_GREEN,/* default */
- GC_NONDEFAULT | COLOR_RED, /* intensified */
- GC_NONDEFAULT | COLOR_BLUE, /* protected */
- GC_NONDEFAULT | COLOR_WHITE /* protected, intensified */
- };
- int i;
-
- ibm_fb = FB_WHITE;
- for (i = 0; i < 16; i++) {
- if (color_name[i] != (char *)NULL)
- XtFree(color_name[i]);
- color_name[i] = XtNewString("white");
- }
- for (i = 0; i < 4; i++)
- field_colors[i] = default_attrib_colors[i];
- }
-
- /* Transfer the colorScheme resource into arrays. */
- static Boolean
- xfer_color_scheme(char *cs, Boolean do_popup)
- {
- int i;
- char *scheme_name = CN;
- char *s0 = CN, *scheme = CN;
- char *tk;
-
- char *tmp_color_name[16];
- enum fallback_color tmp_ibm_fb = FB_WHITE;
- char *tmp_colorbg_name = CN;
- char *tmp_selbg_name = CN;
- int tmp_field_colors[4];
-
- if (cs == CN)
- goto failure;
- scheme_name = xs_buffer("%s.%s", ResColorScheme, cs);
- s0 = get_resource(scheme_name);
- if (s0 == CN) {
- if (do_popup)
- popup_an_error("Can't find resource %s", scheme_name);
- else
- xs_warning("Can't find resource %s", scheme_name);
- goto failure;
- }
- scheme = s0 = XtNewString(s0);
- for (i = 0; (tk = strtok(scheme, " \t\n")) != CN; i++) {
- scheme = CN;
- if (i > 22) {
- xs_warning("Ignoring excess data in %s resource",
- scheme_name);
- break;
- }
- switch (i) {
- case 0: case 1: case 2: case 3:
- case 4: case 5: case 6: case 7:
- case 8: case 9: case 10: case 11:
- case 12: case 13: case 14: case 15: /* IBM color name */
- tmp_color_name[i] = tk;
- break;
- case 16: /* default for IBM colors */
- if (!strcmp(tk, "white"))
- tmp_ibm_fb = FB_WHITE;
- else if (!strcmp(tk, "black"))
- tmp_ibm_fb = FB_BLACK;
- else {
- if (do_popup)
- popup_an_error("Invalid default color");
- else
- xs_warning("Invalid default color");
- goto failure;
- }
- break;
- case 17: /* screen background */
- tmp_colorbg_name = tk;
- break;
- case 18: /* select background */
- tmp_selbg_name = tk;
- break;
- case 19: case 20: case 21: case 22: /* attribute colors */
- tmp_field_colors[i-19] = atoi(tk);
- if (tmp_field_colors[i-19] < 0 ||
- tmp_field_colors[i-19] > 0x0f) {
- if (do_popup)
- popup_an_error("Invalid %s resource, ignoring",
- scheme_name);
- else
- xs_warning("Invalid %s resource, ignoring",
- scheme_name);
- goto failure;
- }
- tmp_field_colors[i-19] |= GC_NONDEFAULT;
- }
- }
- if (i < 23) {
- if (do_popup)
- popup_an_error("Insufficient data in %s resource",
- scheme_name);
- else
- xs_warning("Insufficient data in %s resource",
- scheme_name);
- goto failure;
- }
-
- /* Success: transfer to live variables. */
- for (i = 0; i < 16; i++) {
- if (color_name[i] != (char *)NULL)
- XtFree(color_name[i]);
- color_name[i] = XtNewString(tmp_color_name[i]);
- }
- ibm_fb = tmp_ibm_fb;
- appres.colorbg_name = XtNewString(tmp_colorbg_name);
- appres.selbg_name = XtNewString(tmp_selbg_name);
- for (i = 0; i < 4; i++)
- field_colors[i] = tmp_field_colors[i];
-
- /* Clean up and exit. */
- if (scheme_name != CN)
- XtFree(scheme_name);
- if (s0 != CN)
- XtFree(s0);
- return True;
-
- failure:
- if (scheme_name != CN)
- XtFree(scheme_name);
- if (s0 != CN)
- XtFree(s0);
- return False;
- }
-
- /* Look up a GC, allocating it if necessary. */
- static GC
- get_gc(struct sstate *s, int color)
- {
- int pixel_index;
- XGCValues xgcv;
- GC r;
-
- if (color & GC_NONDEFAULT)
- color &= ~GC_NONDEFAULT;
- else
- color = (color & INVERT_MASK) | DEFAULT_PIXEL;
-
- if ((r = s->gc[color]) != (GC)None)
- return r;
-
- /* Allocate the pixel. */
- pixel_index = PIXEL_INDEX(color);
- if (!cpx_done[pixel_index]) {
- if (!alloc_color(color_name[pixel_index], ibm_fb,
- &cpx[pixel_index])) {
- static char nbuf[16];
-
- (void) sprintf(nbuf, "%d", pixel_index);
- xs_warning("Cannot allocate colormap \"%s\" for 3279 color %s (%s), using \"%s\"",
- color_name[pixel_index], nbuf,
- see_color((unsigned char)(pixel_index + 0xf0)),
- fb_name(ibm_fb));
- }
- cpx_done[pixel_index] = True;
- }
-
- /* Allocate the GC. */
- xgcv.font = s->fid;
- if (!(color & INVERT_MASK)) {
- xgcv.foreground = cpx[pixel_index];
- xgcv.background = colorbg_pixel;
- } else {
- xgcv.foreground = colorbg_pixel;
- xgcv.background = cpx[pixel_index];
- }
- if (s == &nss && pixel_index == DEFAULT_PIXEL) {
- xgcv.graphics_exposures = True;
- r = XtGetGC(toplevel,
- GCForeground|GCBackground|GCFont|GCGraphicsExposures,
- &xgcv);
- } else
- r = XtGetGC(toplevel,
- GCForeground|GCBackground|GCFont,
- &xgcv);
- return s->gc[color] = r;
- }
-
- /* Look up a selection GC, allocating it if necessary. */
- static GC
- get_selgc(struct sstate *s, int color)
- {
- XGCValues xgcv;
- GC r;
-
- if (color & GC_NONDEFAULT)
- color = PIXEL_INDEX(color);
- else
- color = DEFAULT_PIXEL;
-
- if ((r = s->selgc[color]) != (GC)None)
- return r;
-
- /* Allocate the pixel. */
- if (!cpx_done[color]) {
- if (!alloc_color(color_name[color], FB_WHITE, &cpx[color])) {
- static char nbuf[16];
-
- (void) sprintf(nbuf, "%d", color);
- xs_warning("Cannot allocate colormap \"%s\" for 3279 color %s (%s), using \"white\"",
- color_name[color], nbuf,
- see_color((unsigned char)(color + 0xf0)));
- }
- cpx_done[color] = True;
- }
-
- /* Allocate the GC. */
- xgcv.font = s->fid;
- xgcv.foreground = cpx[color];
- xgcv.background = selbg_pixel;
- return s->selgc[color] =
- XtGetGC(toplevel, GCForeground|GCBackground|GCFont, &xgcv);
- }
-
- /* External entry points for GC allocation. */
-
- GC
- screen_gc(int color)
- {
- return get_gc(ss, color | GC_NONDEFAULT);
- }
-
- GC
- screen_invgc(int color)
- {
- return get_gc(ss, INVERT_COLOR(color | GC_NONDEFAULT));
- }
-
- /*
- * Preallocate a set of graphics contexts for a given color.
- *
- * This logic is used only in pseudo-color mode. In full color mode,
- * GCs are allocated dynamically by get_gc().
- */
- static void
- make_gc_set(struct sstate *s, int i, Pixel fg, Pixel bg)
- {
- XGCValues xgcv;
-
- if (s->gc[i] != (GC)None)
- XtReleaseGC(toplevel, s->gc[i]);
- xgcv.foreground = fg;
- xgcv.background = bg;
- xgcv.graphics_exposures = True;
- xgcv.font = s->fid;
- if (s == &nss && !i)
- s->gc[i] = XtGetGC(toplevel,
- GCForeground|GCBackground|GCFont|GCGraphicsExposures,
- &xgcv);
- else
- s->gc[i] = XtGetGC(toplevel,
- GCForeground|GCBackground|GCFont, &xgcv);
- if (s->gc[NGCS + i] != (GC)None)
- XtReleaseGC(toplevel, s->gc[NGCS + i]);
- xgcv.foreground = bg;
- xgcv.background = fg;
- s->gc[NGCS + i] = XtGetGC(toplevel, GCForeground|GCBackground|GCFont,
- &xgcv);
- if (!appres.mono) {
- if (s->selgc[i] != (GC)None)
- XtReleaseGC(toplevel, s->selgc[i]);
- xgcv.foreground = fg;
- xgcv.background = selbg_pixel;
- s->selgc[i] = XtGetGC(toplevel,
- GCForeground|GCBackground|GCFont, &xgcv);
- }
- }
-
-
- /*
- * Convert an attribute to a color index.
- */
- static int
- fa_color(unsigned char fa)
- {
- if (appres.m3279) {
- /*
- * Color indices are the low-order 4 bits of a 3279 color
- * identifier (0 through 15)
- */
- if (appres.modified_sel && FA_IS_MODIFIED(fa))
- return GC_NONDEFAULT |
- (appres.modified_sel_color & 0xf);
- else if (appres.visual_select && FA_IS_SEL(fa))
- return GC_NONDEFAULT |
- (appres.visual_select_color & 0xf);
- else
- return field_colors[(fa >> 1) & 0x03];
- } else {
- /*
- * Color indices are the intensity bits (0 through 2)
- */
- if (FA_IS_ZERO(fa) ||
- (appres.modified_sel && FA_IS_MODIFIED(fa)))
- return GC_NONDEFAULT | FA_INT_NORM_SEL;
- else
- return GC_NONDEFAULT | (fa & FA_INTENSITY);
- }
- }
-
-
-
- /*
- * Event handlers for toplevel FocusIn, FocusOut, KeymapNotify and
- * PropertyChanged events.
- */
-
- static Boolean toplevel_focused = False;
- static Boolean keypad_entered = False;
-
- void
- PA_Focus_action(Widget w unused, XEvent *event, String *params unused,
- Cardinal *num_params unused)
- {
- XFocusChangeEvent *fe = (XFocusChangeEvent *)event;
-
- #if defined(INTERNAL_ACTION_DEBUG) /*[*/
- action_debug(PA_Focus_action, event, params, num_params);
- #endif /*]*/
- switch (fe->type) {
- case FocusIn:
- if (fe->detail != NotifyPointer) {
- toplevel_focused = True;
- screen_focus(True);
- }
- break;
- case FocusOut:
- toplevel_focused = False;
- if (!toplevel_focused && !keypad_entered)
- screen_focus(False);
- break;
- }
- }
-
- void
- PA_EnterLeave_action(Widget w unused, XEvent *event unused,
- String *params unused, Cardinal *num_params unused)
- {
- XCrossingEvent *ce = (XCrossingEvent *)event;
-
- #if defined(INTERNAL_ACTION_DEBUG) /*[*/
- action_debug(PA_EnterLeave_action, event, params, num_params);
- #endif /*]*/
- switch (ce->type) {
- case EnterNotify:
- keypad_entered = True;
- screen_focus(True);
- break;
- case LeaveNotify:
- keypad_entered = False;
- if (!toplevel_focused && !keypad_entered)
- screen_focus(False);
- break;
- }
- }
-
- void
- PA_KeymapNotify_action(Widget w unused, XEvent *event, String *params unused,
- Cardinal *num_params unused)
- {
- XKeymapEvent *k = (XKeymapEvent *)event;
-
- #if defined(INTERNAL_ACTION_DEBUG) /*[*/
- action_debug(PA_KeymapNotify_action, event, params, num_params);
- #endif /*]*/
- shift_event(state_from_keymap(k->key_vector));
- }
-
- static void
- query_window_state(void)
- {
- Atom actual_type;
- int actual_format;
- unsigned long nitems;
- unsigned long leftover;
- unsigned char *data = NULL;
-
- /* If using an active icon, the expose events are more reliable. */
- if (appres.active_icon)
- return;
-
- if (XGetWindowProperty(display, XtWindow(toplevel), a_state, 0L,
- (long)BUFSIZ, False, a_state, &actual_type, &actual_format,
- &nitems, &leftover, &data) != Success)
- return;
- if (actual_type == a_state && actual_format == 32) {
- if (*(unsigned long *)data == IconicState)
- iconic = True;
- else {
- iconic = False;
- invert_icon(False);
- keypad_first_up();
- }
- }
- }
-
- void
- PA_StateChanged_action(Widget w unused, XEvent *event, String *params,
- Cardinal *num_params)
- {
- #if defined(INTERNAL_ACTION_DEBUG) /*[*/
- action_debug(PA_StateChanged_action, event, params, num_params);
- #endif /*]*/
- query_window_state();
- }
-
- /*
- * Handle Shift events (KeyPress and KeyRelease events, or KeymapNotify events
- * that occur when the mouse enters the window).
- */
-
- void
- shift_event(int event_state)
- {
- static int old_state;
- Boolean shifted_now =
- (event_state & (ShiftKeyDown | MetaKeyDown | AltKeyDown)) != 0;
-
- if (event_state != old_state) {
- old_state = event_state;
- status_shift_mode(event_state);
- if (shifted != shifted_now) {
- shifted = shifted_now;
- keypad_shift();
- }
- }
- }
-
- /*
- * Handle the mouse entering and leaving the window.
- */
- static void
- screen_focus(Boolean in)
- {
- /*
- * Cancel any pending cursor blink. If we just came into focus and
- * have a blinking cursor, we will start a fresh blink cycle below, so
- * the filled-in cursor is visible for a full turn.
- */
- cancel_blink();
-
- /*
- * If the cursor is disabled, simply change internal state.
- */
- if (!CONNECTED) {
- in_focus = in;
- return;
- }
-
- /*
- * Change the appearance of the cursor. Make it hollow out or fill in
- * instantly, even if it was blinked off originally.
- */
- (void) cursor_off();
- in_focus = in;
- cursor_on();
-
- /*
- * If we just came into focus and we're supposed to have a blinking
- * cursor, schedule a blink.
- */
- if (in_focus && toggled(CURSOR_BLINK))
- schedule_cursor_blink();
- }
-
- /*
- * Change fonts.
- */
- void
- SetFont_action(Widget w unused, XEvent *event, String *params,
- Cardinal *num_params)
- {
- action_debug(SetFont_action, event, params, num_params);
- if (check_usage(SetFont_action, *num_params, 1, 1) < 0)
- return;
- screen_newfont(params[0], True);
- }
-
- void
- screen_newfont(char *fontname, Boolean do_popup)
- {
- const char *emsg;
- char *old_font;
-
- /* Can't change fonts in APL mode. */
- if (appres.apl_mode)
- return;
-
- if (efontname && !strcmp(fontname, efontname))
- return;
-
- /* Save the old font before trying the new one. */
- old_font = XtNewString(efontname);
-
- /* Try the new one. */
- if ((emsg = load_fixed_font(fontname))) {
- if (do_popup)
- popup_an_error("Font \"%s\"\n%s", fontname, emsg);
- XtFree(old_font);
- return;
- }
-
- /* Store the old name away, in case we have to go back to it. */
- if (redo_old_font != CN)
- XtFree(redo_old_font);
- redo_old_font = old_font;
- screen_redo = REDO_FONT;
-
- screen_reinit(FONT_CHANGE);
- efont_changed = True;
- }
-
- /*
- * Load and query a font.
- * Returns NULL (okay) or an error message.
- */
- static const char *
- load_fixed_font(const char *name)
- {
- XFontStruct *f;
- Font ff;
- char **matches;
- int count;
-
- if (*name == '!') /* backwards compatibility */
- name++;
-
- matches = XListFontsWithInfo(display, name, 1, &count, &f);
- if (matches == (char **)NULL)
- return "does not exist";
- ff = XLoadFont(display, matches[0]);
- set_font_globals(f, name, ff);
- XFreeFontInfo(matches, f, count);
- return CN;
- }
-
- /*
- * Set globals based on font name and info
- */
- static void
- set_font_globals(XFontStruct *f, const char *ef, Font ff)
- {
- unsigned long svalue, svalue2;
-
- if (efontname)
- XtFree(efontname);
- efontname = XtNewString(ef);
- nss.char_width = fCHAR_WIDTH(f);
- nss.char_height = fCHAR_HEIGHT(f);
- nss.fid = ff;
- nss.ascent = f->ascent;
- nss.descent = f->descent;
- if (XGetFontProperty(f, XA_FAMILY_NAME, &svalue))
- nss.standard_font = (Atom) svalue != a_3270;
- else if (!strncmp(efontname, "3270", 4))
- nss.standard_font = False;
- else
- nss.standard_font = True;
- if (nss.standard_font) {
- nss.extended_3270font = False;
- nss.latin1_font =
- f->max_char_or_byte2 > 127 &&
- XGetFontProperty(f, a_registry, &svalue) &&
- (svalue == a_iso8859 || svalue == a_ISO8859) &&
- XGetFontProperty(f, a_encoding, &svalue2) &&
- svalue2 == a_1;
- nss.xfmap = nss.latin1_font ? cg2asc : cg2asc7;
- nss.debugging_font = False;
- } else {
- #if defined(BROKEN_MACH32)
- nss.extended_3270font = False;
- #else
- nss.extended_3270font = f->max_byte1 > 0 ||
- f->max_char_or_byte2 > 255;
- #endif
- nss.latin1_font = False;
- nss.xfmap = (unsigned char *)NULL;
- nss.debugging_font = !strcmp(efontname, "3270d");
- }
- }
-
- /*
- * Font initialization.
- */
- void
- font_init(void)
- {
- char *s, *label, *font;
- struct font_list *f;
- const char *ef, *emsg;
-
- /* Parse the fontMenuList resource. */
- if (!appres.font_list)
- xs_error("No %s resource", ResFontList);
- s = XtNewString(appres.font_list);
- while (split_dresource(&s, &label, &font) == 1) {
- f = (struct font_list *)XtMalloc(sizeof(*f));
- f->label = label;
- f->font = font;
- f->next = (struct font_list *)NULL;
- if (font_list)
- font_last->next = f;
- else
- font_list = f;
- font_last = f;
- font_count++;
- }
- if (!font_count)
- xs_error("Invalid %s resource", ResFontList);
-
- /* Now figure out which emulator font to load and load it. */
- if (appres.apl_mode) {
- /*
- * APL mode overrides any explicit font selection, but if there
- * isn't an APL font defined, APL mode is ignored.
- */
- if ((appres.efontname = appres.afontname) == NULL) {
- xs_warning("No %s resource, ignoring APL mode",
- ResAplFont);
- appres.apl_mode = False;
- }
- }
-
- /*
- * If there's no explicit emulator font, take the first one off the
- * menu list.
- */
- if (!appres.efontname)
- appres.efontname = font_list->font;
-
- /*
- * Try the user's selection, then the first off the menu list, then
- * "fixed", then give up altogether.
- */
- ef = appres.efontname;
- if ((emsg = load_fixed_font(ef)) != CN) {
- xs_warning("%s \"%s\" %s", ResEmulatorFont, ef, emsg);
- if (appres.apl_mode) {
- XtWarning("Ignoring APL mode");
- appres.apl_mode = False;
- }
- if (strcmp(ef, font_list->font)) {
- ef = font_list->font;
- emsg = load_fixed_font(ef);
- if (emsg != CN)
- xs_warning("%s \"%s\" %s", ResEmulatorFont, ef,
- emsg);
- }
- if (emsg != CN) {
- ef = "fixed";
- if ((emsg = load_fixed_font(ef)) != CN)
- xs_error("%s \"%s\" %s", ResEmulatorFont, ef,
- emsg);
- }
- xs_warning("Using font \"%s\"", ef);
- }
- }
-
- #if defined(X3270_MENUS) /*[*/
- /*
- * Change models.
- */
- void
- screen_change_model(int mn, int ovc, int ovr)
- {
- if (CONNECTED ||
- (model_num == mn && ovc == ov_cols && ovr == ov_rows))
- return;
-
- redo_old_model = model_num;
- redo_old_ov_cols = ov_cols;
- redo_old_ov_rows = ov_rows;
- screen_redo = REDO_MODEL;
-
- model_changed = True;
- if (ov_cols != ovc || ov_rows != ovr)
- oversize_changed = True;
- set_rows_cols(mn, ovc, ovr);
- st_changed(ST_REMODEL, True);
- screen_reinit(MODEL_CHANGE);
- }
-
- /*
- * Change emulation modes.
- */
- void
- screen_extended(Boolean extended unused)
- {
- set_rows_cols(model_num, ov_cols, ov_rows);
- model_changed = True;
- }
-
- void
- screen_m3279(Boolean m3279 unused)
- {
- destroy_pixels();
- screen_reinit(COLOR_CHANGE);
- set_rows_cols(model_num, ov_cols, ov_rows);
- model_changed = True;
- }
-
- /*
- * Change color schemes. Alas, this is destructive if it fails.
- */
- void
- screen_newscheme(char *s)
- {
- Boolean xferred;
-
- if (!appres.m3279)
- return;
-
- destroy_pixels();
- xferred = xfer_color_scheme(s, True);
- if (xferred)
- appres.color_scheme = s;
- screen_reinit(COLOR_CHANGE);
- scheme_changed = True;
- }
-
- /*
- * Change character sets.
- */
- void
- screen_newcharset(char *csname)
- {
- if (!charset_init(csname))
- popup_an_error("Cannot find charset \"%s\"", csname);
- else {
- screen_reinit(CHARSET_CHANGE);
- charset_changed = True;
- popup_an_info("The new character set will only be reflected\n"
- "in new data from the host");
- }
- }
- #endif /*]*/
-
- /*
- * Visual or not-so-visual bell
- */
- void
- ring_bell(void)
- {
- static XGCValues xgcv;
- static GC bgc;
- static int initted;
- struct timeval tv;
-
- /* Ring the real display's bell. */
- if (!appres.visual_bell)
- XBell(display, appres.bell_volume);
-
- /* If we're iconic, invert the icon and return. */
- if (!appres.active_icon) {
- query_window_state();
- if (iconic) {
- invert_icon(True);
- return;
- }
- }
-
- if (!appres.visual_bell || !ss->exposed_yet)
- return;
-
- /* Do a screen flash. */
-
- if (!initted) {
- xgcv.function = GXinvert;
- bgc = XtGetGC(toplevel, GCFunction, &xgcv);
- initted = 1;
- }
- screen_disp();
- XFillRectangle(display, ss->window, bgc,
- 0, 0, ss->screen_width, ss->screen_height);
- XSync(display, 0);
- tv.tv_sec = 0;
- tv.tv_usec = 125000;
- (void) select(0, NULL, NULL, NULL, &tv);
- XFillRectangle(display, ss->window, bgc,
- 0, 0, ss->screen_width, ss->screen_height);
- XSync(display, 0);
- }
-
- /*
- * Window deletion
- */
- void
- PA_WMProtocols_action(Widget w, XEvent *event, String *params,
- Cardinal *num_params)
- {
- XClientMessageEvent *cme = (XClientMessageEvent *)event;
-
- #if defined(INTERNAL_ACTION_DEBUG) /*[*/
- action_debug(PA_WMProtocols_action, event, params, num_params);
- #endif /*]*/
- if ((Atom)cme->data.l[0] == a_delete_me) {
- if (w == toplevel)
- x3270_exit(0);
- else
- XtPopdown(w);
- } else if ((Atom)cme->data.l[0] == a_save_yourself && w == toplevel) {
- save_yourself();
- }
- }
-
-
- /* Initialize the icon. */
- void
- icon_init(void)
- {
- icon = XCreateBitmapFromData(display, root_window,
- (char *) x3270_bits, x3270_width, x3270_height);
-
- if (appres.active_icon) {
- Dimension iw, ih;
-
- aicon_font_init();
- aicon_size(&iw, &ih);
- icon_shell = XtVaAppCreateShell(
- "x3270icon",
- "X3270",
- overrideShellWidgetClass,
- display,
- XtNwidth, iw,
- XtNheight, ih,
- XtNmappedWhenManaged, False,
- NULL);
- XtRealizeWidget(icon_shell);
- XtVaSetValues(toplevel,
- XtNiconWindow, XtWindow(icon_shell),
- NULL);
- if (appres.active_icon) {
- XtVaSetValues(icon_shell,
- XtNbackground, appres.mono ? appres.background
- : colorbg_pixel,
- NULL);
- }
- } else {
- unsigned i;
-
- for (i = 0; i < sizeof(x3270_bits); i++)
- x3270_bits[i] = ~x3270_bits[i];
- inv_icon = XCreateBitmapFromData(display, root_window,
- (char *) x3270_bits, x3270_width, x3270_height);
- wait_icon = XCreateBitmapFromData(display, root_window,
- (char *) wait_bits, wait_width, wait_height);
- for (i = 0; i < sizeof(wait_bits); i++)
- wait_bits[i] = ~wait_bits[i];
- inv_wait_icon = XCreateBitmapFromData(display, root_window,
- (char *) wait_bits, wait_width, wait_height);
- XtVaSetValues(toplevel,
- XtNiconPixmap, icon,
- XtNiconMask, icon,
- NULL);
- }
- }
-
- /*
- * Initialize the active icon font information.
- */
- static void
- aicon_font_init(void)
- {
- XFontStruct *f;
- Font ff;
- char **matches;
- int count;
-
- if (!appres.active_icon) {
- appres.label_icon = False;
- return;
- }
-
- matches = XListFontsWithInfo(display, appres.icon_font, 1, &count, &f);
- if (matches == (char **)NULL) {
- xs_warning("No font %s \"%s\"; activeIcon will not work",
- ResIconFont, appres.icon_font);
- appres.active_icon = False;
- return;
- }
- ff = XLoadFont(display, matches[0]);
- iss.char_width = fCHAR_WIDTH(f);
- iss.char_height = fCHAR_HEIGHT(f);
- iss.fid = ff;
- iss.ascent = f->ascent;
- XFreeFontInfo(matches, f, count);
- iss.overstrike = False;
- iss.standard_font = True;
- iss.extended_3270font = False;
- iss.latin1_font = False;
- iss.debugging_font = False;
- iss.obscured = True;
- iss.xfmap = cg2asc7;
- if (appres.label_icon) {
- matches = XListFontsWithInfo(display, appres.icon_label_font,
- 1, &count, &ailabel_font);
- if (matches == (char **)NULL) {
- xs_warning("Cannot load %s \"%s\" font; labelIcon will not work",
- ResIconLabelFont, appres.icon_label_font);
- appres.label_icon = False;
- return;
- }
- ailabel_font->fid = XLoadFont(display, matches[0]);
- aicon_label_height = fCHAR_HEIGHT(ailabel_font) + 2;
- }
- }
-
- /*
- * Determine the current size of the active icon.
- */
- static void
- aicon_size(Dimension *iw, Dimension *ih)
- {
- XIconSize *is;
- int count;
-
- *iw = maxCOLS*iss.char_width + 2*VHALO;
- *ih = maxROWS*iss.char_height + 2*HHALO + aicon_label_height;
- if (XGetIconSizes(display, root_window, &is, &count)) {
- if (*iw > (unsigned) is[0].max_width)
- *iw = is[0].max_width;
- if (*ih > (unsigned) is[0].max_height)
- *ih = is[0].max_height;
- }
- }
-
- /*
- * Initialize the active icon. Assumes that aicon_font_init has already been
- * called.
- */
- static void
- aicon_init(void)
- {
- if (!appres.active_icon)
- return;
-
- iss.widget = icon_shell;
- iss.window = XtWindow(iss.widget);
- iss.cursor_daddr = 0;
- iss.exposed_yet = False;
- if (appres.label_icon) {
- XGCValues xgcv;
-
- xgcv.font = ailabel_font->fid;
- xgcv.foreground = appres.foreground;
- xgcv.background = appres.background;
- ailabel_gc = XtGetGC(toplevel,
- GCFont|GCForeground|GCBackground,
- &xgcv);
- }
- }
-
- /*
- * Reinitialize the active icon.
- */
- static void
- aicon_reinit(unsigned cmask)
- {
- if (!appres.active_icon)
- return;
-
- if (cmask & (FONT_CHANGE | COLOR_CHANGE))
- make_gcs(&iss);
-
- if (cmask & MODEL_CHANGE) {
- aicon_size(&iss.screen_width, &iss.screen_height);
- if (iss.image)
- XtFree((char *) iss.image);
- iss.image = (union sp *)
- XtMalloc(sizeof(union sp) * maxROWS * maxCOLS);
- XtVaSetValues(iss.widget,
- XtNwidth, iss.screen_width,
- XtNheight, iss.screen_height,
- NULL);
- }
- if (cmask & (MODEL_CHANGE | FONT_CHANGE | COLOR_CHANGE))
- (void) memset((char *)iss.image, 0,
- sizeof(union sp) * maxROWS * maxCOLS);
- }
-
- /* Draw the aicon label */
- static void
- draw_aicon_label(void)
- {
- int len;
- Position x;
-
- if (!appres.label_icon || !iconic)
- return;
-
- XFillRectangle(display, iss.window,
- get_gc(&iss, INVERT_COLOR(0)),
- 0, iss.screen_height - aicon_label_height,
- iss.screen_width, aicon_label_height);
- len = strlen(aicon_text);
- x = ((int)iss.screen_width - XTextWidth(ailabel_font, aicon_text, len))
- / 2;
- if (x < 0)
- x = 2;
- XDrawImageString(display, iss.window, ailabel_gc,
- x,
- iss.screen_height - aicon_label_height + ailabel_font->ascent,
- aicon_text, len);
- }
-
- /* Set the aicon label */
- void
- set_aicon_label(char *l)
- {
- if (aicon_text)
- XtFree(aicon_text);
- aicon_text = XtNewString(l);
- draw_aicon_label();
- }
-
- /* Change the bitmap icon. */
- static void
- flip_icon(Boolean inverted, enum mcursor_state mstate)
- {
- Pixmap p = icon;
-
- if (mstate == LOCKED)
- mstate = NORMAL;
- if (appres.active_icon
- || (inverted == icon_inverted && mstate == icon_cstate))
- return;
- switch (mstate) {
- case WAIT:
- if (inverted)
- p = inv_wait_icon;
- else
- p = wait_icon;
- break;
- case LOCKED:
- case NORMAL:
- if (inverted)
- p = inv_icon;
- else
- p = icon;
- break;
- }
- XtVaSetValues(toplevel,
- XtNiconPixmap, p,
- XtNiconMask, p,
- NULL);
- icon_inverted = inverted;
- icon_cstate = mstate;
- }
-
- /*
- * Invert the icon.
- */
- static void
- invert_icon(Boolean inverted)
- {
- flip_icon(inverted, icon_cstate);
- }
-
- /*
- * Change to the lock icon.
- */
- static void
- lock_icon(enum mcursor_state state)
- {
- flip_icon(icon_inverted, state);
- }
-
-
- /*
- * Resize font list parser.
- */
- static void
- init_rsfonts(void)
- {
- char *s;
- char *name;
- struct rsfont *r;
-
- /* Can't resize in APL mode. */
- if (appres.apl_mode)
- return;
-
- if ((s = get_resource(ResResizeFontList)) == CN)
- return;
-
- s = XtNewString(s);
- while (split_lresource(&s, &name) == 1) {
- XFontStruct *f;
- char **matches;
- int count;
-
- matches = XListFontsWithInfo(display, name, 1, &count, &f);
- if (matches == (char **)NULL)
- continue;
- r = (struct rsfont *)XtMalloc(sizeof(*r));
- r->name = name;
- r->width = fCHAR_WIDTH(f);
- r->height = fCHAR_HEIGHT(f);
- XFreeFontInfo(matches, f, count);
- r->next = rsfonts;
- rsfonts = r;
- }
- }
-
- /*
- * Handle ConfigureNotify events.
- */
- static struct {
- Boolean ticking;
- Dimension width, height;
- Position x, y;
- XtIntervalId id;
- } cn = {
- False, 0, 0, 0, 0, 0
- };
- static Position main_x = 0, main_y = 0;
-
- /*
- * Timeout routine called 0.5 sec after x3270 sets new screen dimensions.
- * We assume that if this happens, the window manager is happy with our new
- * size.
- */
- static void
- configure_stable(XtPointer closure unused, XtIntervalId *id unused)
- {
- trace_event("Reconfigure timer expired\n");
- configure_ticking = False;
- if (!cn.ticking)
- screen_redo = REDO_NONE;
- }
-
- /* Perform a resize operation. */
- static void
- do_resize(void)
- {
- struct rsfont *r;
- struct rsfont *best = (struct rsfont *) NULL;
-
- /* What we're doing now is irreversible. */
- screen_redo = REDO_RESIZE;
-
- if (rsfonts == (struct rsfont *)NULL || !appres.allow_resize) {
- /* Illegal or impossible. */
- if (rsfonts == (struct rsfont *)NULL)
- trace_event(" no fonts available for resize\n"
- " reasserting previous size\n");
- else
- trace_event(" resize prohibited by resource\n"
- " reasserting previous size\n");
- set_toplevel_sizes();
- return;
- }
-
- /*
- * Recompute the resulting screen area for each font, based on the
- * current keypad, model, and scrollbar settings.
- */
- for (r = rsfonts; r != (struct rsfont *) NULL; r = r->next) {
- Dimension cw, ch; /* container_width, container_height */
-
- cw = SCREEN_WIDTH(r->width)+2 + scrollbar_width;
- #if defined(X3270_KEYPAD) /*[*/
- {
- Dimension mkw;
-
- mkw = min_keypad_width();
- if (kp_placement == kp_integral
- && appres.keypad_on
- && cw < mkw)
- cw = mkw;
- }
-
- #endif /*]*/
- ch = SCREEN_HEIGHT(r->height)+2 + menubar_qheight(cw);
- #if defined(X3270_KEYPAD) /*[*/
- if (kp_placement == kp_integral && appres.keypad_on)
- ch += keypad_qheight();
- #endif /*]*/
- r->total_width = cw;
- r->total_height = ch;
- r->area = cw * ch;
- }
-
- /*
- * Find the the best match for requested dimensions.
- *
- * In past, the "best" was the closest area that was larger or
- * smaller than the current area, whichever was requested.
- *
- * Now, if they try to shrink the screen, "they" might be the
- * window manager enforcing a size restriction, so the "best"
- * match is the largest window that fits within the requested
- * dimensions.
- *
- * If they try to grow the screen, then the "best" is the
- * smallest font that lies between the current and requested
- * length in the requested dimension(s).
- *
- * An ambiguous request (one dimension larger and the other smaller)
- * is taken to be a "larger" request.
- */
-
- if ((cn.width <= main_width && cn.height <= main_height) ||
- (cn.width > main_width && cn.height > main_height)) {
- /*
- * Shrink or two-dimensional grow: Find the largest font which
- * fits within the new boundaries.
- *
- * Note that a shrink in one dimension, with the other
- * dimension matching, is considered a two-dimensional
- * shrink.
- */
- for (r = rsfonts; r != (struct rsfont *) NULL; r = r->next) {
- if (r->total_width <= cn.width &&
- r->total_height <= cn.height) {
- if (best == NULL || r->area > best->area)
- best = r;
- }
- }
- /*
- * If no font is small enough, see if there is a font smaller
- * than the current font along the requested dimension(s),
- * which is better than doing nothing.
- */
- if (best == NULL) {
- for (r = rsfonts;
- r != (struct rsfont *) NULL;
- r = r->next) {
- if (cn.width < main_width &&
- r->total_width > main_width)
- continue;
- if (cn.height < main_height &&
- r->total_height > main_height)
- continue;
- if (best == NULL ||
- r->area < best->area) {
- best = r;
- }
- }
- }
- } else {
- /*
- * One-dimensional grow: Find the largest font which fits
- * within the lengthened boundary, and don't constrain the
- * other dimension.
- *
- * Note than an ambiguous change (grow in one dimensional and
- * shrink in the other) is considered a one-dimensional grow.
- *
- * In either case, the "other" dimension is considered
- * unconstrained.
- */
- if (cn.width > main_width) {
- /* Wider. */
- for (r = rsfonts;
- r != (struct rsfont *) NULL;
- r = r->next) {
- if (r->total_width <= cn.width &&
- (best == NULL ||
- r->total_width > best->total_width)) {
- best = r;
- }
- }
- } else {
- /* Taller. */
- for (r = rsfonts;
- r != (struct rsfont *) NULL;
- r = r->next) {
- if (r->total_height <= cn.height &&
- (best == NULL ||
- r->total_height > best->total_height)) {
- best = r;
- }
- }
- }
- }
-
- /* Change fonts. */
- if (!best || (efontname && !strcmp(best->name, efontname))) {
- if (cn.width > main_width || cn.height > main_height)
- trace_event(" no larger font available\n"
- " reasserting previous size\n");
- else
- trace_event(" no smaller font available\n"
- " reasserting previous size\n");
- set_toplevel_sizes();
- } else {
- trace_event(" switching to font '%s', new size %dx%d\n",
- best->name, best->total_width, best->total_height);
- screen_newfont(best->name, False);
-
- /* screen_newfont() sets screen_redo to REDO_FONT. */
- screen_redo = REDO_RESIZE;
- }
- }
-
- /*
- * Timeout routine called 0.5 sec after x3270 receives the last ConfigureNotify
- * message. This is for window managers that use 'continuous' move or resize
- * actions.
- */
-
- static void
- stream_end(XtPointer closure unused, XtIntervalId *id unused)
- {
- Boolean needs_moving = False;
- const char *revert = CN;
- char want_size[64];
-
- trace_event("Stream timer expired %hux%hu+%hd+%hd\n",
- cn.width, cn.height, cn.x, cn.y);
-
- /* Not ticking any more. */
- cn.ticking = False;
-
- /* Save the new coordinates in globals for next time. */
- if (cn.x != main_x || cn.y != main_y) {
- main_x = cn.x;
- main_y = cn.y;
- needs_moving = True;
- }
-
- /*
- * If the dimensions are correct, do nothing, forget about any
- * reconfig we may need to revert, and get out.
- */
- if (cn.width == main_width && cn.height == main_height) {
- trace_event(" width and height match\n doing nothing\n");
- screen_redo = REDO_NONE;
- goto done;
- }
-
- /* They're not correct. */
- (void) sprintf(want_size, "%ux%u", main_width, main_height);
- trace_event(" size mismatch, want %s\n", want_size);
-
- /* If there's a reconfiguration pending, try to undo it. */
- switch (screen_redo) {
- case REDO_FONT:
- revert = "font";
- screen_newfont(redo_old_font, False);
- break;
- #if defined(X3270_MENUS) /*[*/
- case REDO_MODEL:
- revert = "model number";
- screen_change_model(redo_old_model,
- redo_old_ov_cols, redo_old_ov_rows);
- break;
- #endif /*]*/
- #if defined(X3270_KEYPAD) /*[*/
- case REDO_KEYPAD:
- revert = "keypad configuration";
- screen_showikeypad(appres.keypad_on = False);
- break;
- #endif /*]*/
- case REDO_SCROLLBAR:
- revert = "scrollbar configuration";
- if (toggled(SCROLL_BAR)) {
- toggle_toggle(&appres.toggle[SCROLL_BAR]);
- toggle_scrollBar(&appres.toggle[SCROLL_BAR],
- TT_TOGGLE);
- }
- break;
- case REDO_RESIZE:
- /* Changed fonts in response to a previous user resize. */
- trace_event(" size reassertion failed, window truncated\n"
- " doing nothing\n");
- screen_redo = REDO_NONE;
- goto done;
- case REDO_NONE:
- /* Initial configuration, or user-generated resize. */
- do_resize();
- goto done;
- default:
- break;
- }
-
- /* Tell the user what we're doing. */
- if (revert != CN) {
- trace_event(" reverting to previous %s\n", revert);
- popup_an_error("Main window does not fit on the "
- "X display\n"
- "Reverting to previous %s", revert);
- }
-
- screen_redo = REDO_NONE;
-
- done:
- if (needs_moving && !iconic)
- keypad_move();
- }
-
- void
- PA_ConfigureNotify_action(Widget w unused, XEvent *event, String *params unused,
- Cardinal *num_params unused)
- {
- XConfigureEvent *re = (XConfigureEvent *) event;
- Position xx, yy;
-
- #if defined(INTERNAL_ACTION_DEBUG) /*[*/
- action_debug(PA_ConfigureNotify_action, event, params, num_params);
- #endif /*]*/
-
- /*
- * Get the new window coordinates. If the configure event reports it
- * as (0,0), ask for it explicitly.
- */
- if (re->x || re->y) {
- xx = re->x;
- yy = re->y;
- } else {
- XtVaGetValues(toplevel, XtNx, &xx, XtNy, &yy, NULL);
- }
- trace_event("ConfigureNotify %hux%hu+%hd+%hd\n",
- re->width, re->height, xx, yy);
-
- /* Save the latest values. */
- cn.x = xx;
- cn.y = yy;
- cn.width = re->width;
- cn.height = re->height;
-
- /* Set the stream timer for 0.5 sec from now. */
- if (cn.ticking)
- XtRemoveTimeOut(cn.id);
- cn.id = XtAppAddTimeOut(appcontext, 500, stream_end, 0);
- cn.ticking = True;
- }
-
- /*
- * Process a VisibilityNotify event, setting the 'visibile' flag in nss.
- * This will switch the behavior of screen scrolling.
- */
- void
- PA_VisibilityNotify_action(Widget w unused, XEvent *event unused,
- String *params unused, Cardinal *num_params unused)
- {
- XVisibilityEvent *e;
-
- #if defined(INTERNAL_ACTION_DEBUG) /*[*/
- action_debug(PA_VisibilityNotify_action, event, params, num_params);
- #endif /*]*/
- e = (XVisibilityEvent *)event;
- nss.obscured = (e->state != VisibilityUnobscured);
- }
-
- /*
- * Process a GraphicsExpose event, refreshing the screen if we have done
- * one or more failed XCopyArea calls.
- */
- void
- PA_GraphicsExpose_action(Widget w unused, XEvent *event unused,
- String *params unused, Cardinal *num_params unused)
- {
- int i;
-
- #if defined(INTERNAL_ACTION_DEBUG) /*[*/
- action_debug(PA_GraphicsExpose_action, event, params, num_params);
- #endif /*]*/
-
- if (nss.copied) {
- /*
- * Force a screen redraw.
- */
- (void) memset((char *) ss->image, 0,
- (maxROWS*maxCOLS) * sizeof(union sp));
- if (ss->debugging_font)
- for (i = 0; i < maxROWS*maxCOLS; i++)
- ss->image[i].bits.cg = CG_space;
- ctlr_changed(0, ROWS*COLS);
- cursor_changed = True;
-
- nss.copied = False;
- }
- }
-
- /* Display size functions. */
- unsigned
- display_width(void)
- {
- return XDisplayWidth(display, default_screen);
- }
-
- unsigned
- display_widthMM(void)
- {
- return XDisplayWidthMM(display, default_screen);
- }
-
- unsigned
- display_height(void)
- {
- return XDisplayHeight(display, default_screen);
- }
-
- unsigned
- display_heightMM(void)
- {
- return XDisplayHeightMM(display, default_screen);
- }
-